/** * Execute glFlush(). * * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the * dd_function_table::Flush driver callback, if not NULL. */ void GLAPIENTRY _mesa_Flush(void) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); _mesa_flush(ctx); }
/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End( void ) { GET_CURRENT_CONTEXT( ctx ); if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (exec->vtx.prim_count > 0) { /* close off current primitive */ int idx = exec->vtx.vert_count; int i = exec->vtx.prim_count - 1; exec->vtx.prim[i].end = 1; exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush( exec, GL_FALSE ); } else _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End(void) { GET_CURRENT_CONTEXT(ctx); struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (!_mesa_inside_begin_end(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd"); return; } ctx->Exec = ctx->OutsideBeginEnd; if (ctx->CurrentClientDispatch == ctx->BeginEnd) { ctx->CurrentClientDispatch = ctx->OutsideBeginEnd; _glapi_set_dispatch(ctx->CurrentClientDispatch); } if (exec->vtx.prim_count > 0) { /* close off current primitive */ struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1]; last_prim->end = 1; last_prim->count = exec->vtx.vert_count - last_prim->start; /* Special handling for GL_LINE_LOOP */ if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) { /* We're finishing drawing a line loop. Append 0th vertex onto * end of vertex buffer so we can draw it as a line strip. */ const fi_type *src = exec->vtx.buffer_map + last_prim->start * exec->vtx.vertex_size; fi_type *dst = exec->vtx.buffer_map + exec->vtx.vert_count * exec->vtx.vertex_size; /* copy 0th vertex to end of buffer */ memcpy(dst, src, exec->vtx.vertex_size * sizeof(fi_type)); last_prim->start++; /* skip vertex0 */ /* note that last_prim->count stays unchanged */ last_prim->mode = GL_LINE_STRIP; /* Increment the vertex count so the next primitive doesn't * overwrite the last vertex which we just added. */ exec->vtx.vert_count++; exec->vtx.buffer_ptr += exec->vtx.vertex_size; } try_vbo_merge(exec); } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush(exec, GL_FALSE); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
GLboolean intelMakeCurrent(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { struct brw_context *brw; GET_CURRENT_CONTEXT(curCtx); if (driContextPriv) brw = (struct brw_context *) driContextPriv->driverPrivate; else brw = NULL; /* According to the glXMakeCurrent() man page: "Pending commands to * the previous context, if any, are flushed before it is released." * But only flush if we're actually changing contexts. */ if (brw_context(curCtx) && brw_context(curCtx) != brw) { _mesa_flush(curCtx); } if (driContextPriv) { struct gl_context *ctx = &brw->ctx; struct gl_framebuffer *fb, *readFb; if (driDrawPriv == NULL && driReadPriv == NULL) { fb = _mesa_get_incomplete_framebuffer(); readFb = _mesa_get_incomplete_framebuffer(); } else { fb = driDrawPriv->driverPrivate; readFb = driReadPriv->driverPrivate; driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; } /* The sRGB workaround changes the renderbuffer's format. We must change * the format before the renderbuffer's miptree get's allocated, otherwise * the formats of the renderbuffer and its miptree will differ. */ intel_gles3_srgb_workaround(brw, fb); intel_gles3_srgb_workaround(brw, readFb); /* If the context viewport hasn't been initialized, force a call out to * the loader to get buffers so we have a drawable size for the initial * viewport. */ if (!brw->ctx.ViewportInitialized) intel_prepare_render(brw); _mesa_make_current(ctx, fb, readFb); } else { _mesa_make_current(NULL, NULL, NULL); } return true; }
GLboolean intelMakeCurrent(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { struct intel_context *intel; GET_CURRENT_CONTEXT(curCtx); if (driContextPriv) intel = (struct intel_context *) driContextPriv->driverPrivate; else intel = NULL; /* According to the glXMakeCurrent() man page: "Pending commands to * the previous context, if any, are flushed before it is released." * But only flush if we're actually changing contexts. */ if (intel_context(curCtx) && intel_context(curCtx) != intel) { _mesa_flush(curCtx); } if (driContextPriv) { struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb, *readFb; if (driDrawPriv == NULL && driReadPriv == NULL) { fb = _mesa_get_incomplete_framebuffer(); readFb = _mesa_get_incomplete_framebuffer(); } else { fb = driDrawPriv->driverPrivate; readFb = driReadPriv->driverPrivate; driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; } intel_prepare_render(intel); _mesa_make_current(ctx, fb, readFb); intel_gles3_srgb_workaround(intel, ctx->WinSysDrawBuffer); intel_gles3_srgb_workaround(intel, ctx->WinSysReadBuffer); /* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer * is NULL at that point. We can't call _mesa_makecurrent() * first, since we need the buffer size for the initial * viewport. So just call intel_draw_buffer() again here. */ intel_draw_buffer(ctx); } else { _mesa_make_current(NULL, NULL, NULL); } return true; }
GLboolean intelMakeCurrent(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { struct brw_context *brw; GET_CURRENT_CONTEXT(curCtx); if (driContextPriv) brw = (struct brw_context *) driContextPriv->driverPrivate; else brw = NULL; /* According to the glXMakeCurrent() man page: "Pending commands to * the previous context, if any, are flushed before it is released." * But only flush if we're actually changing contexts. */ if (brw_context(curCtx) && brw_context(curCtx) != brw) { _mesa_flush(curCtx); } if (driContextPriv) { struct gl_context *ctx = &brw->ctx; struct gl_framebuffer *fb, *readFb; if (driDrawPriv == NULL && driReadPriv == NULL) { fb = _mesa_get_incomplete_framebuffer(); readFb = _mesa_get_incomplete_framebuffer(); } else { fb = driDrawPriv->driverPrivate; readFb = driReadPriv->driverPrivate; driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; } intel_prepare_render(brw); _mesa_make_current(ctx, fb, readFb); intel_gles3_srgb_workaround(brw, ctx->WinSysDrawBuffer); intel_gles3_srgb_workaround(brw, ctx->WinSysReadBuffer); } else { _mesa_make_current(NULL, NULL, NULL); } return true; }
GLboolean intelMakeCurrent(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { struct intel_context *intel; GET_CURRENT_CONTEXT(curCtx); if (driContextPriv) intel = (struct intel_context *) driContextPriv->driverPrivate; else intel = NULL; /* According to the glXMakeCurrent() man page: "Pending commands to * the previous context, if any, are flushed before it is released." * But only flush if we're actually changing contexts. */ if (intel_context(curCtx) && intel_context(curCtx) != intel) { _mesa_flush(curCtx); } if (driContextPriv) { struct gl_framebuffer *fb = driDrawPriv->driverPrivate; struct gl_framebuffer *readFb = driReadPriv->driverPrivate; intel->driReadDrawable = driReadPriv; intel->driDrawable = driDrawPriv; driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; intel_prepare_render(intel); _mesa_make_current(&intel->ctx, fb, readFb); } else { _mesa_make_current(NULL, NULL, NULL); } return GL_TRUE; }
static void vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, struct gl_transform_feedback_object *obj, GLuint stream, GLuint numInstances) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_prim prim[2]; if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream, numInstances)) { return; } vbo_bind_arrays(ctx); /* init most fields to zero */ memset(prim, 0, sizeof(prim)); prim[0].begin = 1; prim[0].end = 1; prim[0].mode = mode; prim[0].num_instances = numInstances; prim[0].base_instance = 0; /* Maybe we should do some primitive splitting for primitive restart * (like in DrawArrays), but we have no way to know how many vertices * will be rendered. */ check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, prim, 1, NULL, GL_TRUE, 0, 0, obj); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * Called via glEnd. */ static void GLAPIENTRY vbo_exec_End( void ) { GET_CURRENT_CONTEXT( ctx ); struct vbo_exec_context *exec = &vbo_context(ctx)->exec; if (!_mesa_inside_begin_end(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glEnd"); return; } ctx->Exec = ctx->OutsideBeginEnd; if (ctx->CurrentDispatch == ctx->BeginEnd) { ctx->CurrentDispatch = ctx->OutsideBeginEnd; _glapi_set_dispatch(ctx->CurrentDispatch); } if (exec->vtx.prim_count > 0) { /* close off current primitive */ int idx = exec->vtx.vert_count; int i = exec->vtx.prim_count - 1; exec->vtx.prim[i].end = 1; exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; try_vbo_merge(exec); } ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; if (exec->vtx.prim_count == VBO_MAX_PRIM) vbo_exec_vtx_flush( exec, GL_FALSE ); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements. * Do the rendering for a glDrawElements or glDrawRangeElements call after * we've validated buffer bounds, etc. */ static void vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, GLboolean index_bounds_valid, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex, GLuint numInstances, GLuint baseInstance) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_index_buffer ib; struct _mesa_prim prim[1]; vbo_bind_arrays(ctx); ib.count = count; ib.type = type; ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; ib.ptr = indices; prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; prim[0].pad = 0; prim[0].mode = mode; prim[0].start = 0; prim[0].count = count; prim[0].indexed = 1; prim[0].basevertex = basevertex; prim[0].num_instances = numInstances; prim[0].base_instance = baseInstance; /* Need to give special consideration to rendering a range of * indices starting somewhere above zero. Typically the * application is issuing multiple DrawRangeElements() to draw * successive primitives layed out linearly in the vertex arrays. * Unless the vertex arrays are all in a VBO (or locked as with * CVA), the OpenGL semantics imply that we need to re-read or * re-upload the vertex data on each draw call. * * In the case of hardware tnl, we want to avoid starting the * upload at zero, as it will mean every draw call uploads an * increasing amount of not-used vertex data. Worse - in the * software tnl module, all those vertices might be transformed and * lit but never rendered. * * If we just upload or transform the vertices in start..end, * however, the indices will be incorrect. * * At this level, we don't know exactly what the requirements of * the backend are going to be, though it will likely boil down to * either: * * 1) Do nothing, everything is in a VBO and is processed once * only. * * 2) Adjust the indices and vertex arrays so that start becomes * zero. * * Rather than doing anything here, I'll provide a helper function * for the latter case elsewhere. */ check_buffers_are_unmapped(exec->array.inputs); vbo_handle_primitive_restart(ctx, prim, 1, &ib, index_bounds_valid, start, end); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * Helper function called by the other DrawArrays() functions below. * This is where we handle primitive restart for drawing non-indexed * arrays. If primitive restart is enabled, it typically means * splitting one DrawArrays() into two. */ static void vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start, GLsizei count, GLuint numInstances, GLuint baseInstance) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_prim prim[2]; vbo_bind_arrays(ctx); /* init most fields to zero */ memset(prim, 0, sizeof(prim)); prim[0].begin = 1; prim[0].end = 1; prim[0].mode = mode; prim[0].num_instances = numInstances; prim[0].base_instance = baseInstance; /* Implement the primitive restart index */ if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) { GLuint primCount = 0; if (ctx->Array.RestartIndex == start) { /* special case: RestartIndex at beginning */ if (count > 1) { prim[0].start = start + 1; prim[0].count = count - 1; primCount = 1; } } else if (ctx->Array.RestartIndex == start + count - 1) { /* special case: RestartIndex at end */ if (count > 1) { prim[0].start = start; prim[0].count = count - 1; primCount = 1; } } else { /* general case: RestartIndex in middle, split into two prims */ prim[0].start = start; prim[0].count = ctx->Array.RestartIndex - start; prim[1] = prim[0]; prim[1].start = ctx->Array.RestartIndex + 1; prim[1].count = count - prim[1].start; primCount = 2; } if (primCount > 0) { /* draw one or two prims */ check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, prim, primCount, NULL, GL_TRUE, start, start + count - 1, NULL); } } else { /* no prim restart */ prim[0].start = start; prim[0].count = count; check_buffers_are_unmapped(exec->array.inputs); vbo->draw_prims(ctx, prim, 1, NULL, GL_TRUE, start, start + count - 1, NULL); } if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/** * Inner support for both _mesa_MultiDrawElements() and * _mesa_MultiDrawRangeElements(). * This does the actual rendering after we've checked array indexes, etc. */ static void vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, const GLsizei *count, GLenum type, const GLvoid * const *indices, GLsizei primcount, const GLint *basevertex) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_index_buffer ib; struct _mesa_prim *prim; unsigned int index_type_size = vbo_sizeof_ib_type(type); uintptr_t min_index_ptr, max_index_ptr; GLboolean fallback = GL_FALSE; int i; if (primcount == 0) return; prim = calloc(1, primcount * sizeof(*prim)); if (prim == NULL) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements"); return; } vbo_bind_arrays(ctx); min_index_ptr = (uintptr_t)indices[0]; max_index_ptr = 0; for (i = 0; i < primcount; i++) { min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]); max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] + index_type_size * count[i]); } /* Check if we can handle this thing as a bunch of index offsets from the * same index pointer. If we can't, then we have to fall back to doing * a draw_prims per primitive. * Check that the difference between each prim's indexes is a multiple of * the index/element size. */ if (index_type_size != 1) { for (i = 0; i < primcount; i++) { if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) { fallback = GL_TRUE; break; } } } /* If the index buffer isn't in a VBO, then treating the application's * subranges of the index buffer as one large index buffer may lead to * us reading unmapped memory. */ if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) fallback = GL_TRUE; if (!fallback) { ib.count = (max_index_ptr - min_index_ptr) / index_type_size; ib.type = type; ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; ib.ptr = (void *)min_index_ptr; for (i = 0; i < primcount; i++) { prim[i].begin = (i == 0); prim[i].end = (i == primcount - 1); prim[i].weak = 0; prim[i].pad = 0; prim[i].mode = mode; prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size; prim[i].count = count[i]; prim[i].indexed = 1; prim[i].num_instances = 1; prim[i].base_instance = 0; if (basevertex != NULL) prim[i].basevertex = basevertex[i]; else prim[i].basevertex = 0; } check_buffers_are_unmapped(exec->array.inputs); vbo_handle_primitive_restart(ctx, prim, primcount, &ib, GL_FALSE, ~0, ~0); } else { /* render one prim at a time */ for (i = 0; i < primcount; i++) { ib.count = count[i]; ib.type = type; ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj; ib.ptr = indices[i]; prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; prim[0].pad = 0; prim[0].mode = mode; prim[0].start = 0; prim[0].count = count[i]; prim[0].indexed = 1; prim[0].num_instances = 1; prim[0].base_instance = 0; if (basevertex != NULL) prim[0].basevertex = basevertex[i]; else prim[0].basevertex = 0; check_buffers_are_unmapped(exec->array.inputs); vbo_handle_primitive_restart(ctx, prim, 1, &ib, GL_FALSE, ~0, ~0); } } free(prim); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
/* * Execute glDrawPixels */ 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)" ); return; } /* We're not using the current vertex program, and the driver may install * its own. Note: this may dirty some state. */ _mesa_set_vp_override(ctx, GL_TRUE); /* Note: this call does state validation */ if (!_mesa_valid_to_render(ctx, "glDrawPixels")) { goto end; /* the error code was recorded */ } /* 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; } 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; } /* 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 */ } if (ctx->RenderMode == GL_RENDER) { if (width > 0 && height > 0) { /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ GLint x = IROUND(ctx->Current.RasterPos[0]); GLint y = IROUND(ctx->Current.RasterPos[1]); if (_mesa_is_bufferobj(ctx->Unpack.BufferObj)) { /* unpack from PBO */ 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; } if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)"); goto end; } } ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, &ctx->Unpack, pixels); } } else if (ctx->RenderMode == GL_FEEDBACK) { /* Feedback the current raster pos info */ FLUSH_CURRENT( ctx, 0 ); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } end: _mesa_set_vp_override(ctx, GL_FALSE); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
static void GLAPIENTRY _mesa_Bitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (width < 0 || height < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); return; } if (!ctx->Current.RasterPosValid) { return; /* do nothing */ } /* Note: this call does state validation */ if (!_mesa_valid_to_render(ctx, "glBitmap")) { /* the error code was recorded */ return; } if (ctx->RasterDiscard) return; if (ctx->RenderMode == GL_RENDER) { /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ if (width > 0 && height > 0) { const GLfloat epsilon = 0.0001F; GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig); GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig); 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, INT_MAX, (const GLvoid *) bitmap)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(invalid PBO access)"); return; } if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); return; } } ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); } } #if _HAVE_FULL_GL else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT(ctx, 0); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } #endif /* update raster position */ ctx->Current.RasterPos[0] += xmove; ctx->Current.RasterPos[1] += ymove; if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }
static void GLAPIENTRY _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLenum type ) { 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; } /* Note: more detailed 'type' checking is done by the * _mesa_source/dest_buffer_exists() calls below. That's where we * check if the stencil buffer exists, etc. */ if (type != GL_COLOR && type != GL_DEPTH && type != GL_STENCIL && type != GL_DEPTH_STENCIL) { _mesa_error(ctx, GL_INVALID_ENUM, "glCopyPixels(type=%s)", _mesa_lookup_enum_by_nr(type)); return; } /* We're not using the current vertex program, and the driver may install * it's own. Note: this may dirty some state. */ _mesa_set_vp_override(ctx, GL_TRUE); /* Note: this call does state validation */ if (!_mesa_valid_to_render(ctx, "glCopyPixels")) { goto end; /* the error code was recorded */ } /* 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 (_mesa_is_user_fbo(ctx->ReadBuffer) && ctx->ReadBuffer->Visual.samples > 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels(multisample FBO)"); goto end; } if (!_mesa_source_buffer_exists(ctx, type) || !_mesa_dest_buffer_exists(ctx, type)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyPixels(missing source or dest buffer)"); goto end; } if (ctx->RasterDiscard) { goto end; } if (!ctx->Current.RasterPosValid || width == 0 || height == 0) { goto end; /* no-op, not an error */ } if (ctx->RenderMode == GL_RENDER) { /* Round to satisfy conformance tests (matches SGI's OpenGL) */ if (width > 0 && height > 0) { GLint destx = IROUND(ctx->Current.RasterPos[0]); GLint desty = IROUND(ctx->Current.RasterPos[1]); ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type ); } } else if (ctx->RenderMode == GL_FEEDBACK) { FLUSH_CURRENT( ctx, 0 ); _mesa_feedback_token( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); _mesa_feedback_vertex( ctx, ctx->Current.RasterPos, ctx->Current.RasterColor, ctx->Current.RasterTexCoords[0] ); } else { ASSERT(ctx->RenderMode == GL_SELECT); /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ } end: _mesa_set_vp_override(ctx, GL_FALSE); if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } }