X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fdrawpix.c;h=49b078289c801ebab635e47069ceda264c1f32aa;hb=9ad8f431b2a47060bf05517246ab0fa8d249c800;hp=5d4b53af4cbec89a8b0fa0def63e1444b0ada3a6;hpb=1f196b786d6bd0c6a5dbdc638574ff716cc3d4de;p=mesa.git diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index 5d4b53af4cb..49b078289c8 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -31,25 +31,16 @@ #include "feedback.h" #include "framebuffer.h" #include "image.h" -#include "readpix.h" +#include "mfeatures.h" +#include "pbo.h" #include "state.h" -#include "glapi/dispatch.h" +#include "dispatch.h" +#include "glformats.h" #if FEATURE_drawpix -/** - * If a fragment program is enabled, check that it's valid. - * \return GL_TRUE if valid, GL_FALSE otherwise - */ -static GLboolean -valid_fragment_program(GLcontext *ctx) -{ - return !(ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled); -} - - /* * Execute glDrawPixels */ @@ -57,42 +48,95 @@ static void GLAPIENTRY _mesa_DrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) { + GLenum err; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glDrawPixels(%d, %d, %s, %s, %p) // to %s at %d, %d\n", + width, height, + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type), + pixels, + _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + IROUND(ctx->Current.RasterPos[0]), + IROUND(ctx->Current.RasterPos[1])); + + if (width < 0 || height < 0) { - _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); + _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0)" ); return; } /* We're not using the current vertex program, and the driver may install - * it's own. + * its own. Note: this may dirty some state. */ _mesa_set_vp_override(ctx, GL_TRUE); - if (ctx->NewState) { - _mesa_update_state(ctx); + /* Note: this call does state validation */ + if (!_mesa_valid_to_render(ctx, "glDrawPixels")) { + goto end; /* the error code was recorded */ } - if (!valid_fragment_program(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawPixels (invalid fragment program)"); + /* GL 3.0 introduced a new restriction on glDrawPixels() over what was in + * GL_EXT_texture_integer. From section 3.7.4 ("Rasterization of Pixel + * Rectangles) on page 151 of the GL 3.0 specification: + * + * "If format contains integer components, as shown in table 3.6, an + * INVALID OPERATION error is generated." + * + * Since DrawPixels rendering would be merely undefined if not an error (due + * to a lack of defined mapping from integer data to gl_Color fragment shader + * input), NVIDIA's implementation also just returns this error despite + * exposing GL_EXT_texture_integer, just return an error regardless. + */ + if (_mesa_is_enum_format_integer(format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(integer format)"); goto end; } - if (_mesa_error_check_format_type(ctx, format, type, GL_TRUE)) { - /* the error was already recorded */ + err = _mesa_error_check_format_and_type(ctx, format, type); + if (err != GL_NO_ERROR) { + _mesa_error(ctx, err, "glDrawPixels(invalid format %s and/or type %s)", + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(type)); goto end; } - if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glDrawPixels(incomplete framebuffer)" ); + /* do special format-related checks */ + switch (format) { + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_EXT: + /* these buffers must exist */ + if (!_mesa_dest_buffer_exists(ctx, format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawPixels(missing deest buffer)"); + goto end; + } + break; + case GL_COLOR_INDEX: + if (ctx->PixelMaps.ItoR.Size == 0 || + ctx->PixelMaps.ItoG.Size == 0 || + ctx->PixelMaps.ItoB.Size == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawPixels(drawing color index pixels into RGB buffer)"); + goto end; + } + break; + default: + /* for color formats it's not an error if the destination color + * buffer doesn't exist. + */ + break; + } + + if (ctx->RasterDiscard) { goto end; } if (!ctx->Current.RasterPosValid) { - goto end; /* no-op, not an error */ + goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { @@ -101,10 +145,10 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, GLint x = IROUND(ctx->Current.RasterPos[0]); GLint y = IROUND(ctx->Current.RasterPos[1]); - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack from PBO */ - if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, - format, type, pixels)) { + if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, + 1, format, type, INT_MAX, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(invalid PBO access)"); goto end; @@ -128,7 +172,6 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, - ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { @@ -138,6 +181,10 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, end: _mesa_set_vp_override(ctx, GL_FALSE); + + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { + _mesa_flush(ctx); + } } @@ -148,6 +195,16 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glCopyPixels(%d, %d, %d, %d, %s) // from %s to %s at %d, %d\n", + srcx, srcy, width, height, + _mesa_lookup_enum_by_nr(type), + _mesa_lookup_enum_by_nr(ctx->ReadBuffer->ColorReadBuffer), + _mesa_lookup_enum_by_nr(ctx->DrawBuffer->ColorDrawBuffer[0]), + IROUND(ctx->Current.RasterPos[0]), + IROUND(ctx->Current.RasterPos[1])); + if (width < 0 || height < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)"); return; @@ -167,24 +224,25 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, } /* We're not using the current vertex program, and the driver may install - * it's own. + * it's own. Note: this may dirty some state. */ _mesa_set_vp_override(ctx, GL_TRUE); - if (ctx->NewState) { - _mesa_update_state(ctx); + /* Note: this call does state validation */ + if (!_mesa_valid_to_render(ctx, "glCopyPixels")) { + goto end; /* the error code was recorded */ } - if (!valid_fragment_program(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyPixels (invalid fragment program)"); + /* Check read buffer's status (draw buffer was already checked) */ + if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glCopyPixels(incomplete framebuffer)" ); goto end; } - if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || - ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glCopyPixels(incomplete framebuffer)" ); + if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyPixels(multisample FBO)"); goto end; } @@ -195,7 +253,11 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, goto end; } - if (!ctx->Current.RasterPosValid || width ==0 || height == 0) { + if (ctx->RasterDiscard) { + goto end; + } + + if (!ctx->Current.RasterPosValid || width == 0 || height == 0) { goto end; /* no-op, not an error */ } @@ -214,7 +276,6 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, - ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { @@ -224,6 +285,10 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, end: _mesa_set_vp_override(ctx, GL_FALSE); + + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { + _mesa_flush(ctx); + } } @@ -244,21 +309,14 @@ _mesa_Bitmap( GLsizei width, GLsizei height, return; /* do nothing */ } - if (ctx->NewState) { - _mesa_update_state(ctx); - } - - if (!valid_fragment_program(ctx)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBitmap (invalid fragment program)"); + /* Note: this call does state validation */ + if (!_mesa_valid_to_render(ctx, "glBitmap")) { + /* the error code was recorded */ return; } - if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glBitmap(incomplete framebuffer)"); + if (ctx->RasterDiscard) return; - } if (ctx->RenderMode == GL_RENDER) { /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ @@ -267,11 +325,11 @@ _mesa_Bitmap( GLsizei width, GLsizei height, GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig); GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig); - if (ctx->Unpack.BufferObj->Name) { + if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack from PBO */ - if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, - GL_COLOR_INDEX, GL_BITMAP, - (GLvoid *) bitmap)) { + if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, + 1, GL_COLOR_INDEX, GL_BITMAP, + INT_MAX, (const GLvoid *) bitmap)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(invalid PBO access)"); return; @@ -294,7 +352,6 @@ _mesa_Bitmap( GLsizei width, GLsizei height, _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, - ctx->Current.RasterIndex, ctx->Current.RasterTexCoords[0] ); } else { @@ -306,6 +363,10 @@ _mesa_Bitmap( GLsizei width, GLsizei height, /* update raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; + + if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { + _mesa_flush(ctx); + } }