void GL_APIENTRY _mesa_ClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha) { _mesa_ClearColor((GLclampf) (red / 65536.0f), (GLclampf) (green / 65536.0f), (GLclampf) (blue / 65536.0f), (GLclampf) (alpha / 65536.0f)); }
bool _mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *tex_image, int xoffset, int yoffset, int zoffset, int width, int height, int depth, GLenum format, GLenum type, const void *pixels, const struct gl_pixelstore_attrib *packing) { GLuint pbo = 0, pbo_tex = 0, fbos[2] = { 0, 0 }; int image_height; struct gl_texture_image *pbo_tex_image; struct gl_renderbuffer *rb = NULL; GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format); GLenum status, src_base_format; bool success = false, clear_channels_to_zero = false; float save_clear_color[4]; int z; if (!_mesa_is_bufferobj(packing->BufferObj)) return false; if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL || format == GL_STENCIL_INDEX || format == GL_COLOR_INDEX) return false; /* Don't use meta path for readpixels in below conditions. */ if (!tex_image) { rb = ctx->ReadBuffer->_ColorReadBuffer; /* _mesa_get_readpixels_transfer_ops() includes the cases of read * color clamping along with the ctx->_ImageTransferState. */ if (_mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type, GL_FALSE)) return false; if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat)) return false; /* This function rely on BlitFramebuffer to fill in the pixel data for * ReadPixels. But, BlitFrameBuffer doesn't support signed to unsigned * or unsigned to signed integer conversions. OpenGL spec expects an * invalid operation in that case. */ if (need_signed_unsigned_int_conversion(rb->Format, format, type)) return false; } /* For arrays, use a tall (height * depth) 2D texture but taking into * account the inter-image padding specified with the image height packing * property. */ image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight; pbo_tex_image = create_texture_for_pbo(ctx, false, GL_PIXEL_PACK_BUFFER, dims, width, height, depth, format, type, pixels, packing, &pbo, &pbo_tex); if (!pbo_tex_image) return false; _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER | MESA_META_PIXEL_STORE)); /* GL_CLAMP_FRAGMENT_COLOR doesn't affect ReadPixels and GettexImage */ if (ctx->Extensions.ARB_color_buffer_float) _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); _mesa_GenFramebuffers(2, fbos); if (tex_image && tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { assert(depth == 1); assert(zoffset == 0); depth = height; height = 1; image_height = 1; zoffset = yoffset; yoffset = 0; } /* If we were given a texture, bind it to the read framebuffer. If not, * we're doing a ReadPixels and we should just use whatever framebuffer * the client has bound. */ if (tex_image) { _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_image, zoffset); /* If this passes on the first layer it should pass on the others */ status = _mesa_CheckFramebufferStatus(GL_READ_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; } else { assert(depth == 1); } _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); _mesa_meta_bind_fbo_image(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pbo_tex_image, 0); /* If this passes on the first layer it should pass on the others */ status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; _mesa_update_state(ctx); if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, xoffset, yoffset, xoffset + width, yoffset + height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST)) goto fail; src_base_format = tex_image ? tex_image->_BaseFormat : ctx->ReadBuffer->_ColorReadBuffer->_BaseFormat; /* Depending on the base formats involved we might need to rebase some * values. For example if we download from a Luminance format to RGBA * format, we want G=0 and B=0. */ clear_channels_to_zero = _mesa_need_luminance_to_rgb_conversion(src_base_format, pbo_tex_image->_BaseFormat); if (clear_channels_to_zero) { memcpy(save_clear_color, ctx->Color.ClearColor.f, 4 * sizeof(float)); /* Clear the Green, Blue channels. */ _mesa_ColorMask(GL_FALSE, GL_TRUE, GL_TRUE, src_base_format != GL_LUMINANCE_ALPHA); _mesa_ClearColor(0.0, 0.0, 0.0, 1.0); _mesa_Clear(GL_COLOR_BUFFER_BIT); } for (z = 1; z < depth; z++) { _mesa_meta_bind_fbo_image(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_image, zoffset + z); _mesa_update_state(ctx); _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, xoffset, yoffset, xoffset + width, yoffset + height, 0, z * image_height, width, z * image_height + height, GL_COLOR_BUFFER_BIT, GL_NEAREST); if (clear_channels_to_zero) _mesa_Clear(GL_COLOR_BUFFER_BIT); } /* Unmask the color channels and restore the saved clear color values. */ if (clear_channels_to_zero) { _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); _mesa_ClearColor(save_clear_color[0], save_clear_color[1], save_clear_color[2], save_clear_color[3]); } success = true; fail: _mesa_DeleteFramebuffers(2, fbos); _mesa_DeleteTextures(1, &pbo_tex); _mesa_DeleteBuffers(1, &pbo); _mesa_meta_end(ctx); return success; }
/* * This function is kind of long just because we have to call a lot * of device driver functions to update device driver state. * * XXX As it is now, most of the pop-code calls immediate-mode Mesa functions * in order to restore GL state. This isn't terribly efficient but it * ensures that dirty flags and any derived state gets updated correctly. * We could at least check if the value to restore equals the current value * and then skip the Mesa call. */ void _mesa_PopAttrib(void) { struct gl_attrib_node *attr, *next; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (ctx->AttribStackDepth == 0) { _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" ); return; } ctx->AttribStackDepth--; attr = ctx->AttribStack[ctx->AttribStackDepth]; while (attr) { if (MESA_VERBOSE&VERBOSE_API) { fprintf(stderr, "glPopAttrib %s\n", _mesa_lookup_enum_by_nr(attr->kind)); } switch (attr->kind) { case GL_ACCUM_BUFFER_BIT: { const struct gl_accum_attrib *accum; accum = (const struct gl_accum_attrib *) attr->data; _mesa_ClearAccum(accum->ClearColor[0], accum->ClearColor[1], accum->ClearColor[2], accum->ClearColor[3]); } break; case GL_COLOR_BUFFER_BIT: { const struct gl_colorbuffer_attrib *color; color = (const struct gl_colorbuffer_attrib *) attr->data; _mesa_ClearIndex((GLfloat) color->ClearIndex); _mesa_ClearColor(CHAN_TO_FLOAT(color->ClearColor[0]), CHAN_TO_FLOAT(color->ClearColor[1]), CHAN_TO_FLOAT(color->ClearColor[2]), CHAN_TO_FLOAT(color->ClearColor[3])); _mesa_IndexMask(color->IndexMask); _mesa_ColorMask((GLboolean) (color->ColorMask[0] != 0), (GLboolean) (color->ColorMask[1] != 0), (GLboolean) (color->ColorMask[2] != 0), (GLboolean) (color->ColorMask[3] != 0)); _mesa_DrawBuffer(color->DrawBuffer); _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled); _mesa_AlphaFunc(color->AlphaFunc, CHAN_TO_FLOAT(color->AlphaRef)); _mesa_set_enable(ctx, GL_BLEND, color->BlendEnabled); _mesa_BlendFuncSeparateEXT(color->BlendSrcRGB, color->BlendDstRGB, color->BlendSrcA, color->BlendDstA); _mesa_BlendEquation(color->BlendEquation); _mesa_BlendColor(color->BlendColor[0], color->BlendColor[1], color->BlendColor[2], color->BlendColor[3]); _mesa_LogicOp(color->LogicOp); _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, color->ColorLogicOpEnabled); _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP, color->IndexLogicOpEnabled); _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag); } break; case GL_CURRENT_BIT: FLUSH_CURRENT( ctx, 0 ); MEMCPY( &ctx->Current, attr->data, sizeof(struct gl_current_attrib) ); break; case GL_DEPTH_BUFFER_BIT: { const struct gl_depthbuffer_attrib *depth; depth = (const struct gl_depthbuffer_attrib *) attr->data; _mesa_DepthFunc(depth->Func); _mesa_ClearDepth(depth->Clear); _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test); _mesa_DepthMask(depth->Mask); if (ctx->Extensions.HP_occlusion_test) _mesa_set_enable(ctx, GL_OCCLUSION_TEST_HP, depth->OcclusionTest); } break; case GL_ENABLE_BIT: { const struct gl_enable_attrib *enable; enable = (const struct gl_enable_attrib *) attr->data; pop_enable_group(ctx, enable); ctx->NewState |= _NEW_ALL; } break; case GL_EVAL_BIT: MEMCPY( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) ); ctx->NewState |= _NEW_EVAL; break; case GL_FOG_BIT: { const struct gl_fog_attrib *fog; fog = (const struct gl_fog_attrib *) attr->data; _mesa_set_enable(ctx, GL_FOG, fog->Enabled); _mesa_Fogfv(GL_FOG_COLOR, fog->Color); _mesa_Fogf(GL_FOG_DENSITY, fog->Density); _mesa_Fogf(GL_FOG_START, fog->Start); _mesa_Fogf(GL_FOG_END, fog->End); _mesa_Fogf(GL_FOG_INDEX, fog->Index); _mesa_Fogi(GL_FOG_MODE, fog->Mode); } break; case GL_HINT_BIT: { const struct gl_hint_attrib *hint; hint = (const struct gl_hint_attrib *) attr->data; _mesa_Hint(GL_PERSPECTIVE_CORRECTION_HINT, hint->PerspectiveCorrection ); _mesa_Hint(GL_POINT_SMOOTH_HINT, hint->PointSmooth); _mesa_Hint(GL_LINE_SMOOTH_HINT, hint->LineSmooth); _mesa_Hint(GL_POLYGON_SMOOTH_HINT, hint->PolygonSmooth); _mesa_Hint(GL_FOG_HINT, hint->Fog); _mesa_Hint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, hint->ClipVolumeClipping); if (ctx->Extensions.ARB_texture_compression) _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB, hint->TextureCompression); } break; case GL_LIGHTING_BIT: { GLuint i; const struct gl_light_attrib *light; light = (const struct gl_light_attrib *) attr->data; /* lighting enable */ _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled); /* per-light state */ if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) _math_matrix_analyse( &ctx->ModelView ); for (i = 0; i < MAX_LIGHTS; i++) { GLenum lgt = (GLenum) (GL_LIGHT0 + i); const struct gl_light *l = &light->Light[i]; GLfloat tmp[4]; _mesa_set_enable(ctx, lgt, l->Enabled); _mesa_Lightfv( lgt, GL_AMBIENT, l->Ambient ); _mesa_Lightfv( lgt, GL_DIFFUSE, l->Diffuse ); _mesa_Lightfv( lgt, GL_SPECULAR, l->Specular ); TRANSFORM_POINT( tmp, ctx->ModelView.inv, l->EyePosition ); _mesa_Lightfv( lgt, GL_POSITION, tmp ); TRANSFORM_POINT( tmp, ctx->ModelView.m, l->EyeDirection ); _mesa_Lightfv( lgt, GL_SPOT_DIRECTION, tmp ); _mesa_Lightfv( lgt, GL_SPOT_EXPONENT, &l->SpotExponent ); _mesa_Lightfv( lgt, GL_SPOT_CUTOFF, &l->SpotCutoff ); _mesa_Lightfv( lgt, GL_CONSTANT_ATTENUATION, &l->ConstantAttenuation ); _mesa_Lightfv( lgt, GL_LINEAR_ATTENUATION, &l->LinearAttenuation ); _mesa_Lightfv( lgt, GL_QUADRATIC_ATTENUATION, &l->QuadraticAttenuation ); } /* light model */ _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT, light->Model.Ambient); _mesa_LightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, (GLfloat) light->Model.LocalViewer); _mesa_LightModelf(GL_LIGHT_MODEL_TWO_SIDE, (GLfloat) light->Model.TwoSide); _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL, (GLfloat) light->Model.ColorControl); /* materials */ MEMCPY(ctx->Light.Material, light->Material, 2 * sizeof(struct gl_material)); /* shade model */ _mesa_ShadeModel(light->ShadeModel); /* color material */ _mesa_ColorMaterial(light->ColorMaterialFace, light->ColorMaterialMode); _mesa_set_enable(ctx, GL_COLOR_MATERIAL, light->ColorMaterialEnabled); } break; case GL_LINE_BIT: { const struct gl_line_attrib *line; line = (const struct gl_line_attrib *) attr->data; _mesa_set_enable(ctx, GL_LINE_SMOOTH, line->SmoothFlag); _mesa_set_enable(ctx, GL_LINE_STIPPLE, line->StippleFlag); _mesa_LineStipple(line->StippleFactor, line->StipplePattern); _mesa_LineWidth(line->Width); } break; case GL_LIST_BIT: MEMCPY( &ctx->List, attr->data, sizeof(struct gl_list_attrib) ); break; case GL_PIXEL_MODE_BIT: MEMCPY( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) ); ctx->NewState |= _NEW_PIXEL; break; case GL_POINT_BIT: { const struct gl_point_attrib *point; point = (const struct gl_point_attrib *) attr->data; _mesa_PointSize(point->Size); _mesa_set_enable(ctx, GL_POINT_SMOOTH, point->SmoothFlag); if (ctx->Extensions.EXT_point_parameters) { _mesa_PointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, point->Params); _mesa_PointParameterfEXT(GL_POINT_SIZE_MIN_EXT, point->MinSize); _mesa_PointParameterfEXT(GL_POINT_SIZE_MAX_EXT, point->MaxSize); _mesa_PointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, point->Threshold); } } break; case GL_POLYGON_BIT: { const struct gl_polygon_attrib *polygon; polygon = (const struct gl_polygon_attrib *) attr->data; _mesa_CullFace(polygon->CullFaceMode); _mesa_FrontFace(polygon->FrontFace); _mesa_PolygonMode(GL_FRONT, polygon->FrontMode); _mesa_PolygonMode(GL_BACK, polygon->BackMode); _mesa_PolygonOffset(polygon->OffsetFactor, polygon->OffsetUnits); _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, polygon->SmoothFlag); _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, polygon->StippleFlag); _mesa_set_enable(ctx, GL_CULL_FACE, polygon->CullFlag); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_POINT, polygon->OffsetPoint); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_LINE, polygon->OffsetLine); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, polygon->OffsetFill); } break; case GL_POLYGON_STIPPLE_BIT: MEMCPY( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) ); ctx->NewState |= _NEW_POLYGONSTIPPLE; if (ctx->Driver.PolygonStipple) ctx->Driver.PolygonStipple( ctx, (const GLubyte *) attr->data ); break; case GL_SCISSOR_BIT: { const struct gl_scissor_attrib *scissor; scissor = (const struct gl_scissor_attrib *) attr->data; _mesa_Scissor(scissor->X, scissor->Y, scissor->Width, scissor->Height); _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->Enabled); } break; case GL_STENCIL_BUFFER_BIT: { const struct gl_stencil_attrib *stencil; stencil = (const struct gl_stencil_attrib *) attr->data; _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); _mesa_ClearStencil(stencil->Clear); _mesa_StencilFunc(stencil->Function, stencil->Ref, stencil->ValueMask); _mesa_StencilMask(stencil->WriteMask); _mesa_StencilOp(stencil->FailFunc, stencil->ZFailFunc, stencil->ZPassFunc); } break; case GL_TRANSFORM_BIT: { GLuint i; const struct gl_transform_attrib *xform; xform = (const struct gl_transform_attrib *) attr->data; _mesa_MatrixMode(xform->MatrixMode); if (ctx->ProjectionMatrix.flags & MAT_DIRTY) _math_matrix_analyse( &ctx->ProjectionMatrix ); /* restore clip planes */ for (i = 0; i < MAX_CLIP_PLANES; i++) { const GLfloat *eyePlane = xform->EyeUserPlane[i]; COPY_4V(ctx->Transform.EyeUserPlane[i], eyePlane); if (xform->ClipEnabled[i]) { _mesa_transform_vector( ctx->Transform._ClipUserPlane[i], eyePlane, ctx->ProjectionMatrix.inv ); _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE ); } else { _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE ); } if (ctx->Driver.ClipPlane) ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, eyePlane ); } /* normalize/rescale */ _mesa_set_enable(ctx, GL_NORMALIZE, ctx->Transform.Normalize); _mesa_set_enable(ctx, GL_RESCALE_NORMAL_EXT, ctx->Transform.RescaleNormals); } break; case GL_TEXTURE_BIT: /* Take care of texture object reference counters */ { const struct gl_texture_attrib *texture; texture = (const struct gl_texture_attrib *) attr->data; pop_texture_group(ctx, texture); ctx->NewState |= _NEW_TEXTURE; } break; case GL_VIEWPORT_BIT: { const struct gl_viewport_attrib *vp; vp = (const struct gl_viewport_attrib *) attr->data; _mesa_Viewport(vp->X, vp->Y, vp->Width, vp->Height); _mesa_DepthRange(vp->Near, vp->Far); } break; case GL_MULTISAMPLE_BIT_ARB: { const struct gl_multisample_attrib *ms; ms = (const struct gl_multisample_attrib *) attr->data; _mesa_SampleCoverageARB(ms->SampleCoverageValue, ms->SampleCoverageInvert); } break; default: _mesa_problem( ctx, "Bad attrib flag in PopAttrib"); break; } next = attr->next; FREE( attr->data ); FREE( attr ); attr = next; } }