/** * Update the hardware state for drawing into a window or framebuffer object. * * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other * places within the driver. * * Basically, this needs to be called any time the current framebuffer * changes, the renderbuffers change, or we need to draw into different * color buffers. */ static void brw_update_draw_buffer(struct intel_context *intel) { struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; if (!fb) { /* this can happen during the initial context initialization */ return; } /* Do this here, not core Mesa, since this function is called from * many places within the driver. */ if (ctx->NewState & _NEW_BUFFERS) { /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ _mesa_update_framebuffer(ctx); /* this updates the DrawBuffer's Width/Height if it's a FBO */ _mesa_update_draw_buffer_bounds(ctx); } if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { /* this may occur when we're called by glBindFrameBuffer() during * the process of someone setting up renderbuffers, etc. */ /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ return; } /* Mesa's Stencil._Enabled field is updated when * _NEW_BUFFERS | _NEW_STENCIL, but i965 code assumes that the value * only changes with _NEW_STENCIL (which seems sensible). So flag it * here since this is the _NEW_BUFFERS path. */ intel->NewGLState |= (_NEW_DEPTH | _NEW_STENCIL); /* The driver uses this in places that need to look up * renderbuffers' buffer objects. */ intel->NewGLState |= _NEW_BUFFERS; /* update viewport/scissor since it depends on window size */ intel->NewGLState |= _NEW_VIEWPORT | _NEW_SCISSOR; /* Update culling direction which changes depending on the * orientation of the buffer: */ intel->NewGLState |= _NEW_POLYGON; }
void _mesa_blit_framebuffer(struct gl_context *ctx, struct gl_framebuffer *readFb, struct gl_framebuffer *drawFb, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, const char *func) { const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); FLUSH_VERTICES(ctx, 0); /* Update completeness status of readFb and drawFb. */ _mesa_update_framebuffer(ctx, readFb, drawFb); /* Make sure drawFb has an initialized bounding box. */ _mesa_update_draw_buffer_bounds(ctx, drawFb); if (!readFb || !drawFb) { /* This will normally never happen but someday we may want to * support MakeCurrent() with no drawables. */ return; } /* check for complete framebuffers */ if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "%s(incomplete draw/read buffers)", func); return; } if (!is_valid_blit_filter(ctx, filter)) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func, _mesa_enum_to_string(filter)); return; } if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT || filter == GL_SCALED_RESOLVE_NICEST_EXT) && (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func, _mesa_enum_to_string(filter)); return; } if (mask & ~legalMaskBits) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func); return; } /* depth/stencil must be blitted with nearest filtering */ if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) && filter != GL_NEAREST) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(depth/stencil requires GL_NEAREST filter)", func); return; } /* get color read/draw renderbuffers */ if (mask & GL_COLOR_BUFFER_BIT) { const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers; const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if (!colorReadRb || numColorDrawBuffers == 0) { mask &= ~GL_COLOR_BUFFER_BIT; } else { for (i = 0; i < numColorDrawBuffers; i++) { colorDrawRb = drawFb->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL * ES 3.0.1 spec says: * * "If the source and destination buffers are identical, an * INVALID_OPERATION error is generated. Different mipmap * levels of a texture, different layers of a three- * dimensional texture or two-dimensional array texture, and * different faces of a cube map texture do not constitute * identical buffers." */ if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(source and destination color " "buffer cannot be the same)", func); return; } if (!compatible_color_datatypes(colorReadRb->Format, colorDrawRb->Format)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(color buffer datatypes mismatch)", func); return; } /* extra checks for multisample copies... */ if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { /* color formats must match on GLES. This isn't checked on * desktop GL because the GL 4.4 spec was changed to allow it. * In the section entitled “Changes in the released * Specification of July 22, 2013” it says: * * “Relax BlitFramebuffer in section 18.3.1 so that format * conversion can take place during multisample blits, since * drivers already allow this and some apps depend on it.” */ if (_mesa_is_gles(ctx) && !compatible_resolve_formats(colorReadRb, colorDrawRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(bad src/dst multisample pixel formats)", func); return; } } } if (filter != GL_NEAREST) { /* From EXT_framebuffer_multisample_blit_scaled specification: * "Calling BlitFramebuffer will result in an INVALID_OPERATION error * if filter is not NEAREST and read buffer contains integer data." */ GLenum type = _mesa_get_format_datatype(colorReadRb->Format); if (type == GL_INT || type == GL_UNSIGNED_INT) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(integer color type)", func); return; } } } } if (mask & GL_STENCIL_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->Attachment[BUFFER_STENCIL].Renderbuffer; struct gl_renderbuffer *drawRb = drawFb->Attachment[BUFFER_STENCIL].Renderbuffer; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_STENCIL_BUFFER_BIT; } else { int read_z_bits, draw_z_bits; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(source and destination stencil " "buffer cannot be the same)", func); return; } if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { /* There is no need to check the stencil datatype here, because * there is only one: GL_UNSIGNED_INT. */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil attachment format mismatch)", func); return; } read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS); draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS); /* If both buffers also have depth data, the depth formats must match * as well. If one doesn't have depth, it's not blitted, so we should * ignore the depth format check. */ if (read_z_bits > 0 && draw_z_bits > 0 && (read_z_bits != draw_z_bits || _mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil attachment depth format mismatch)", func); return; } } } if (mask & GL_DEPTH_BUFFER_BIT) { struct gl_renderbuffer *readRb = readFb->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *drawRb = drawFb->Attachment[BUFFER_DEPTH].Renderbuffer; /* From the EXT_framebuffer_object spec: * * "If a buffer is specified in <mask> and does not exist in both * the read and draw framebuffers, the corresponding bit is silently * ignored." */ if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_DEPTH_BUFFER_BIT; } else { int read_s_bit, draw_s_bit; if (_mesa_is_gles3(ctx) && (drawRb == readRb)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(source and destination depth " "buffer cannot be the same)", func); return; } if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || (_mesa_get_format_datatype(readRb->Format) != _mesa_get_format_datatype(drawRb->Format))) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(depth attachment format mismatch)", func); return; } read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS); draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS); /* If both buffers also have stencil data, the stencil formats must * match as well. If one doesn't have stencil, it's not blitted, so * we should ignore the stencil format check. */ if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(depth attachment stencil bits mismatch)", func); return; } } } if (_mesa_is_gles3(ctx)) { /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES * 3.0.1 spec says: * * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero, * an INVALID_OPERATION error is generated." */ if (drawFb->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(destination samples must be 0)", func); return; } /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES * 3.0.1 spec says: * * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero, * no copy is performed and an INVALID_OPERATION error is generated * if the formats of the read and draw framebuffers are not * identical or if the source and destination rectangles are not * defined with the same (X0, Y0) and (X1, Y1) bounds." * * The format check was made above because desktop OpenGL has the same * requirement. */ if (readFb->Visual.samples > 0 && (srcX0 != dstX0 || srcY0 != dstY0 || srcX1 != dstX1 || srcY1 != dstY1)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(bad src/dst multisample region)", func); return; } } else { if (readFb->Visual.samples > 0 && drawFb->Visual.samples > 0 && readFb->Visual.samples != drawFb->Visual.samples) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(mismatched samples)", func); return; } /* extra checks for multisample copies... */ if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) && (filter == GL_NEAREST || filter == GL_LINEAR)) { /* src and dest region sizes must be the same */ if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) || abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(bad src/dst multisample region sizes)", func); return; } } } /* Debug code */ if (DEBUG_BLIT) { const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; const struct gl_renderbuffer *colorDrawRb = NULL; GLuint i = 0; printf("%s(%d, %d, %d, %d, %d, %d, %d, %d," " 0x%x, 0x%x)\n", func, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); if (colorReadRb) { const struct gl_renderbuffer_attachment *att; att = find_attachment(readFb, colorReadRb); printf(" Src FBO %u RB %u (%dx%d) ", readFb->Name, colorReadRb->Name, colorReadRb->Width, colorReadRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", att->Texture->Name, att->Texture->Target, att->TextureLevel, att->CubeMapFace); } printf("\n"); /* Print all active color render buffers */ for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) { colorDrawRb = drawFb->_ColorDrawBuffers[i]; if (!colorDrawRb) continue; att = find_attachment(drawFb, colorDrawRb); printf(" Dst FBO %u RB %u (%dx%d) ", drawFb->Name, colorDrawRb->Name, colorDrawRb->Width, colorDrawRb->Height); if (att && att->Texture) { printf("Tex %u tgt 0x%x level %u face %u", att->Texture->Name, att->Texture->Target, att->TextureLevel, att->CubeMapFace); } printf("\n"); } } } if (!mask || (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 || (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) { return; } assert(ctx->Driver.BlitFramebuffer); ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); }
/** * Compute derived GL state. * If __GLcontextRec::NewState is non-zero then this function \b must * be called before rendering anything. * * Calls dd_function_table::UpdateState to perform any internal state * management necessary. * * \sa _mesa_update_modelview_project(), _mesa_update_texture(), * _mesa_update_buffer_bounds(), * _mesa_update_lighting() and _mesa_update_tnl_spaces(). */ void _mesa_update_state_locked( GLcontext *ctx ) { GLbitfield new_state = ctx->NewState; GLbitfield prog_flags = _NEW_PROGRAM; GLbitfield new_prog_state = 0x0; if (new_state == _NEW_CURRENT_ATTRIB) goto out; if (MESA_VERBOSE & VERBOSE_STATE) _mesa_print_state("_mesa_update_state", new_state); /* Determine which state flags effect vertex/fragment program state */ if (ctx->FragmentProgram._MaintainTexEnvProgram) { prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR | _NEW_ARRAY); } if (ctx->VertexProgram._MaintainTnlProgram) { prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | _NEW_TRANSFORM | _NEW_POINT | _NEW_FOG | _NEW_LIGHT | _MESA_NEW_NEED_EYE_COORDS); } /* * Now update derived state info */ if (new_state & prog_flags) update_program_enables( ctx ); if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) _mesa_update_modelview_project( ctx, new_state ); if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) _mesa_update_texture( ctx, new_state ); if (new_state & _NEW_BUFFERS) _mesa_update_framebuffer(ctx); if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) _mesa_update_draw_buffer_bounds( ctx ); if (new_state & _NEW_POLYGON) update_polygon( ctx ); if (new_state & _NEW_LIGHT) _mesa_update_lighting( ctx ); if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) _mesa_update_stencil( ctx ); #if FEATURE_pixel_transfer if (new_state & _MESA_NEW_TRANSFER_STATE) _mesa_update_pixel( ctx, new_state ); #endif if (new_state & _DD_NEW_SEPARATE_SPECULAR) update_separate_specular( ctx ); if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) update_arrays( ctx ); if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT)) update_viewport_matrix(ctx); if (new_state & _NEW_MULTISAMPLE) update_multisample( ctx ); if (new_state & _NEW_COLOR) update_color( ctx ); #if 0 if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR)) update_tricaps( ctx, new_state ); #endif /* ctx->_NeedEyeCoords is now up to date. * * If the truth value of this variable has changed, update for the * new lighting space and recompute the positions of lights and the * normal transform. * * If the lighting space hasn't changed, may still need to recompute * light positions & normal transforms for other reasons. */ if (new_state & _MESA_NEW_NEED_EYE_COORDS) _mesa_update_tnl_spaces( ctx, new_state ); if (new_state & prog_flags) { /* When we generate programs from fixed-function vertex/fragment state * this call may generate/bind a new program. If so, we need to * propogate the _NEW_PROGRAM flag to the driver. */ new_prog_state |= update_program( ctx ); } out: new_prog_state |= update_program_constants(ctx); /* * Give the driver a chance to act upon the new_state flags. * The driver might plug in different span functions, for example. * Also, this is where the driver can invalidate the state of any * active modules (such as swrast_setup, swrast, tnl, etc). * * Set ctx->NewState to zero to avoid recursion if * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) */ new_state = ctx->NewState | new_prog_state; ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); ctx->Array.NewState = 0; }
/** * Update the hardware state for drawing into a window or framebuffer object. * * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other * places within the driver. * * Basically, this needs to be called any time the current framebuffer * changes, the renderbuffers change, or we need to draw into different * color buffers. */ void intel_draw_buffer(struct gl_context * ctx, struct gl_framebuffer *fb) { struct intel_context *intel = intel_context(ctx); struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL; struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; if (!fb) { /* this can happen during the initial context initialization */ return; } /* Do this here, not core Mesa, since this function is called from * many places within the driver. */ if (ctx->NewState & _NEW_BUFFERS) { /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ _mesa_update_framebuffer(ctx); /* this updates the DrawBuffer's Width/Height if it's a FBO */ _mesa_update_draw_buffer_bounds(ctx); } if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { /* this may occur when we're called by glBindFrameBuffer() during * the process of someone setting up renderbuffers, etc. */ /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ return; } /* How many color buffers are we drawing into? * * If there are zero buffers or the buffer is too big, don't configure any * regions for hardware drawing. We'll fallback to software below. Not * having regions set makes some of the software fallback paths faster. */ if ((fb->Width > ctx->Const.MaxRenderbufferSize) || (fb->Height > ctx->Const.MaxRenderbufferSize) || (fb->_NumColorDrawBuffers == 0)) { /* writing to 0 */ colorRegions[0] = NULL; } else if (fb->_NumColorDrawBuffers > 1) { int i; struct intel_renderbuffer *irb; for (i = 0; i < fb->_NumColorDrawBuffers; i++) { irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]); colorRegions[i] = irb ? irb->region : NULL; } } else { /* Get the intel_renderbuffer for the single colorbuffer we're drawing * into. */ if (fb->Name == 0) { /* drawing to window system buffer */ if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); else colorRegions[0] = intel_get_rb_region(fb, BUFFER_BACK_LEFT); } else { /* drawing to user-created FBO */ struct intel_renderbuffer *irb; irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); colorRegions[0] = (irb && irb->region) ? irb->region : NULL; } } if (!colorRegions[0]) { FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); } else { FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); } /*** *** Get depth buffer region and check if we need a software fallback. *** Note that the depth buffer is usually a DEPTH_STENCIL buffer. ***/ if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) { irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped); if (irbDepth && irbDepth->region) { FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); depthRegion = irbDepth->region; } else { FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE); depthRegion = NULL; } } else { /* not using depth buffer */ FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); depthRegion = NULL; } /*** *** Stencil buffer *** This can only be hardware accelerated if we're using a *** combined DEPTH_STENCIL buffer. ***/ if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) { irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped); if (irbStencil && irbStencil->region) { ASSERT(irbStencil->Base.Format == MESA_FORMAT_S8_Z24); FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); } else { FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE); } } else { /* XXX FBO: instead of FALSE, pass ctx->Stencil._Enabled ??? */ FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); } /* If we have a (packed) stencil buffer attached but no depth buffer, * we still need to set up the shared depth/stencil state so we can use it. */ if (depthRegion == NULL && irbStencil && irbStencil->region) depthRegion = irbStencil->region; /* * Update depth and stencil test state */ if (ctx->Driver.Enable) { ctx->Driver.Enable(ctx, GL_DEPTH_TEST, (ctx->Depth.Test && fb->Visual.depthBits > 0)); ctx->Driver.Enable(ctx, GL_STENCIL_TEST, (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0)); } else { /* Mesa's Stencil._Enabled field is updated when * _NEW_BUFFERS | _NEW_STENCIL, but i965 code assumes that the value * only changes with _NEW_STENCIL (which seems sensible). So flag it * here since this is the _NEW_BUFFERS path. */ intel->NewGLState |= (_NEW_DEPTH | _NEW_STENCIL); } intel->vtbl.set_draw_region(intel, colorRegions, depthRegion, fb->_NumColorDrawBuffers); intel->NewGLState |= _NEW_BUFFERS; /* update viewport since it depends on window size */ #ifdef I915 intelCalcViewport(ctx); #else intel->NewGLState |= _NEW_VIEWPORT; #endif /* Set state we know depends on drawable parameters: */ if (ctx->Driver.Scissor) ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, ctx->Scissor.Width, ctx->Scissor.Height); intel->NewGLState |= _NEW_SCISSOR; if (ctx->Driver.DepthRange) ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); /* Update culling direction which changes depending on the * orientation of the buffer: */ if (ctx->Driver.FrontFace) ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); else intel->NewGLState |= _NEW_POLYGON; }
/** * Compute derived GL state. * If __struct gl_contextRec::NewState is non-zero then this function \b must * be called before rendering anything. * * Calls dd_function_table::UpdateState to perform any internal state * management necessary. * * \sa _mesa_update_modelview_project(), _mesa_update_texture(), * _mesa_update_buffer_bounds(), * _mesa_update_lighting() and _mesa_update_tnl_spaces(). */ void _mesa_update_state_locked( struct gl_context *ctx ) { GLbitfield new_state = ctx->NewState; GLbitfield new_prog_state = 0x0; const GLbitfield computed_states = ~(_NEW_CURRENT_ATTRIB | _NEW_LINE); /* we can skip a bunch of state validation checks if the dirty * state matches one or more bits in 'computed_states'. */ if ((new_state & computed_states) == 0) goto out; if (MESA_VERBOSE & VERBOSE_STATE) _mesa_print_state("_mesa_update_state", new_state); if (new_state & _NEW_BUFFERS) _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer); /* Handle Core and Compatibility contexts separately. */ if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { GLbitfield prog_flags = _NEW_PROGRAM; /* Determine which state flags effect vertex/fragment program state */ if (ctx->FragmentProgram._MaintainTexEnvProgram) { prog_flags |= (_NEW_BUFFERS | _NEW_TEXTURE_OBJECT | _NEW_FOG | _NEW_VARYING_VP_INPUTS | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE | _NEW_PROGRAM | _NEW_FRAG_CLAMP | _NEW_COLOR | _NEW_TEXTURE_STATE); } if (ctx->VertexProgram._MaintainTnlProgram) { prog_flags |= (_NEW_VARYING_VP_INPUTS | _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_MATRIX | _NEW_TRANSFORM | _NEW_POINT | _NEW_FOG | _NEW_LIGHT | _NEW_TEXTURE_STATE | _MESA_NEW_NEED_EYE_COORDS); } /* * Now update derived state info */ if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) _mesa_update_modelview_project( ctx, new_state ); if (new_state & _NEW_TEXTURE_MATRIX) _mesa_update_texture_matrices(ctx); if (new_state & (_NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE | _NEW_PROGRAM)) _mesa_update_texture_state(ctx); if (new_state & _NEW_LIGHT) _mesa_update_lighting(ctx); if (new_state & _NEW_PIXEL) _mesa_update_pixel( ctx ); /* ctx->_NeedEyeCoords is now up to date. * * If the truth value of this variable has changed, update for the * new lighting space and recompute the positions of lights and the * normal transform. * * If the lighting space hasn't changed, may still need to recompute * light positions & normal transforms for other reasons. */ if (new_state & _MESA_NEW_NEED_EYE_COORDS) _mesa_update_tnl_spaces( ctx, new_state ); if (new_state & prog_flags) { /* When we generate programs from fixed-function vertex/fragment state * this call may generate/bind a new program. If so, we need to * propogate the _NEW_PROGRAM flag to the driver. */ new_prog_state |= update_program(ctx); } } else { /* GL Core and GLES 2/3 contexts */ if (new_state & (_NEW_TEXTURE_OBJECT | _NEW_PROGRAM)) _mesa_update_texture_state(ctx); if (new_state & _NEW_PROGRAM) update_program(ctx); } out: new_prog_state |= update_program_constants(ctx); ctx->NewState |= new_prog_state; vbo_exec_invalidate_state(ctx); /* * Give the driver a chance to act upon the new_state flags. * The driver might plug in different span functions, for example. * Also, this is where the driver can invalidate the state of any * active modules (such as swrast_setup, swrast, tnl, etc). */ ctx->Driver.UpdateState(ctx); ctx->NewState = 0; }
/** * Compute derived GL state. * If __struct gl_contextRec::NewState is non-zero then this function \b must * be called before rendering anything. * * Calls dd_function_table::UpdateState to perform any internal state * management necessary. * * \sa _mesa_update_modelview_project(), _mesa_update_texture(), * _mesa_update_buffer_bounds(), * _mesa_update_lighting() and _mesa_update_tnl_spaces(). */ void _mesa_update_state_locked( struct gl_context *ctx ) { GLbitfield new_state = ctx->NewState; GLbitfield prog_flags = _NEW_PROGRAM; GLbitfield new_prog_state = 0x0; const GLbitfield computed_states = ~(_NEW_CURRENT_ATTRIB | _NEW_LINE); /* we can skip a bunch of state validation checks if the dirty * state matches one or more bits in 'computed_states'. */ if ((new_state & computed_states) == 0) goto out; if (MESA_VERBOSE & VERBOSE_STATE) _mesa_print_state("_mesa_update_state", new_state); /* Determine which state flags effect vertex/fragment program state */ if (ctx->FragmentProgram._MaintainTexEnvProgram) { prog_flags |= (_NEW_BUFFERS | _NEW_TEXTURE | _NEW_FOG | _NEW_VARYING_VP_INPUTS | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE | _NEW_PROGRAM | _NEW_FRAG_CLAMP | _NEW_COLOR); } if (ctx->VertexProgram._MaintainTnlProgram) { prog_flags |= (_NEW_VARYING_VP_INPUTS | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | _NEW_TRANSFORM | _NEW_POINT | _NEW_FOG | _NEW_LIGHT | _MESA_NEW_NEED_EYE_COORDS); } /* * Now update derived state info */ if (new_state & prog_flags) update_program_enables( ctx ); if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) _mesa_update_modelview_project( ctx, new_state ); if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) _mesa_update_texture( ctx, new_state ); if (new_state & _NEW_POLYGON) update_frontbit( ctx ); if (new_state & _NEW_BUFFERS) _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer); if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); if (new_state & _NEW_LIGHT) _mesa_update_lighting( ctx ); if (new_state & (_NEW_LIGHT | _NEW_PROGRAM)) update_twoside( ctx ); if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) _mesa_update_stencil( ctx ); if (new_state & _NEW_PIXEL) _mesa_update_pixel( ctx, new_state ); /* ctx->_NeedEyeCoords is now up to date. * * If the truth value of this variable has changed, update for the * new lighting space and recompute the positions of lights and the * normal transform. * * If the lighting space hasn't changed, may still need to recompute * light positions & normal transforms for other reasons. */ if (new_state & _MESA_NEW_NEED_EYE_COORDS) _mesa_update_tnl_spaces( ctx, new_state ); if (new_state & prog_flags) { /* When we generate programs from fixed-function vertex/fragment state * this call may generate/bind a new program. If so, we need to * propogate the _NEW_PROGRAM flag to the driver. */ new_prog_state |= update_program( ctx ); } if (new_state & _NEW_ARRAY) _mesa_update_vao_client_arrays(ctx, ctx->Array.VAO); out: new_prog_state |= update_program_constants(ctx); /* * Give the driver a chance to act upon the new_state flags. * The driver might plug in different span functions, for example. * Also, this is where the driver can invalidate the state of any * active modules (such as swrast_setup, swrast, tnl, etc). * * Set ctx->NewState to zero to avoid recursion if * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) */ new_state = ctx->NewState | new_prog_state; ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); ctx->Array.VAO->NewArrays = 0x0; }