void GLAPIENTRY _mesa_ViewportIndexedf_no_error(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { GET_CURRENT_CONTEXT(ctx); _mesa_set_viewport(ctx, index, x, y, w, h); }
/** * Set the viewport. * * \param x, y coordinates of the lower-left corner of the viewport rectangle. * \param width width of the viewport rectangle. * \param height height of the viewport rectangle. * * \sa Called via glViewport() or display list execution. * * Flushes the vertices and calls _mesa_set_viewport() with the given * parameters. */ void GLAPIENTRY _mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height ) { GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); _mesa_set_viewport(ctx, x, y, width, height); }
/* Force the context `c' to be the current context and associate with it * buffer `b'. */ GLboolean r128MakeCurrent( __DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driDrawPriv, __DRIdrawablePrivate *driReadPriv ) { if ( driContextPriv ) { GET_CURRENT_CONTEXT(ctx); r128ContextPtr oldR128Ctx = ctx ? R128_CONTEXT(ctx) : NULL; r128ContextPtr newR128Ctx = (r128ContextPtr) driContextPriv->driverPrivate; if ( newR128Ctx != oldR128Ctx ) { newR128Ctx->new_state |= R128_NEW_CONTEXT; newR128Ctx->dirty = R128_UPLOAD_ALL; } newR128Ctx->driDrawable = driDrawPriv; _mesa_make_current2( newR128Ctx->glCtx, (GLframebuffer *) driDrawPriv->driverPrivate, (GLframebuffer *) driReadPriv->driverPrivate ); newR128Ctx->new_state |= R128_NEW_WINDOW | R128_NEW_CLIP; if ( !newR128Ctx->glCtx->Viewport.Width ) { _mesa_set_viewport(newR128Ctx->glCtx, 0, 0, driDrawPriv->w, driDrawPriv->h); } } else { _mesa_make_current( 0, 0 ); } return GL_TRUE; }
static void viewport_indexed_err(struct gl_context *ctx, GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h, const char *function) { if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "%s(%d, %f, %f, %f, %f)\n", function, index, x, y, w, h); if (index >= ctx->Const.MaxViewports) { _mesa_error(ctx, GL_INVALID_VALUE, "%s: index (%d) >= MaxViewports (%d)", function, index, ctx->Const.MaxViewports); return; } /* Verify width & height */ if (w < 0 || h < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "%s: index (%d) width or height < 0 (%f, %f)", function, index, w, h); return; } _mesa_set_viewport(ctx, index, x, y, w, h); }
/** * Check if the viewport/scissor size has not yet been initialized. * Initialize the size if the given width and height are non-zero. */ void _mesa_check_init_viewport(GLcontext *ctx, GLuint width, GLuint height) { if (!ctx->ViewportInitialized && width > 0 && height > 0) { /* Note: set flag here, before calling _mesa_set_viewport(), to prevent * potential infinite recursion. */ ctx->ViewportInitialized = GL_TRUE; _mesa_set_viewport(ctx, 0, 0, width, height); _mesa_set_scissor(ctx, 0, 0, width, height); } }
void GalliumContext::ResizeViewport(int32 width, int32 height) { CALLED(); for (context_id i = 0; i < CONTEXT_MAX; i++) { if (fContext[i] && fContext[i]->st) { struct st_context *stContext = (struct st_context*)fContext[i]->st; _mesa_set_viewport(stContext->ctx, 0, 0, 0, width, height); st_manager_validate_framebuffers(stContext); } } }
/* Force the context `c' to be the current context and associate with it * buffer `b'. */ GLboolean radeonMakeCurrent( __DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driDrawPriv, __DRIdrawablePrivate *driReadPriv ) { if ( driContextPriv ) { radeonContextPtr newCtx = (radeonContextPtr) driContextPriv->driverPrivate; if (RADEON_DEBUG & DEBUG_DRI) fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)newCtx->glCtx); if ( newCtx->dri.drawable != driDrawPriv ) { newCtx->dri.drawable = driDrawPriv; radeonUpdateWindow( newCtx->glCtx ); radeonUpdateViewportOffset( newCtx->glCtx ); } _mesa_make_current2( newCtx->glCtx, (GLframebuffer *) driDrawPriv->driverPrivate, (GLframebuffer *) driReadPriv->driverPrivate ); if ( !newCtx->glCtx->Viewport.Width ) { _mesa_set_viewport( newCtx->glCtx, 0, 0, driDrawPriv->w, driDrawPriv->h ); } if (newCtx->vb.enabled) radeonVtxfmtMakeCurrent( newCtx->glCtx ); } else { if (RADEON_DEBUG & DEBUG_DRI) fprintf(stderr, "%s ctx is null\n", __FUNCTION__); _mesa_make_current( 0, 0 ); } if (RADEON_DEBUG & DEBUG_DRI) fprintf(stderr, "End %s\n", __FUNCTION__); return GL_TRUE; }
void st_make_current(struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read) { if (st) { GLboolean firstTime = st->ctx->FirstTimeCurrent; _mesa_make_current(st->ctx, &draw->Base, &read->Base); /* Need to initialize viewport here since draw->Base->Width/Height * will still be zero at this point. * This could be improved, but would require rather extensive work * elsewhere (allocate rb surface storage sooner) */ if (firstTime) { GLuint w = draw->InitWidth, h = draw->InitHeight; _mesa_set_viewport(st->ctx, 0, 0, w, h); _mesa_set_scissor(st->ctx, 0, 0, w, h); } } else { _mesa_make_current(NULL, NULL, NULL); } }
/** * Leave meta state. This is like a light-weight version of glPopAttrib(). */ void _mesa_meta_end(struct gl_context *ctx) { struct save_state *save = &ctx->Meta->Save[--ctx->Meta->SaveStackDepth]; const GLbitfield state = save->SavedState; if (state & MESA_META_ALPHA_TEST) { if (ctx->Color.AlphaEnabled != save->AlphaEnabled) _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled); _mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef); } if (state & MESA_META_BLEND) { if (ctx->Color.BlendEnabled != save->BlendEnabled) { _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1)); } if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled) _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled); } if (state & MESA_META_COLOR_MASK) { if (!TEST_EQ_4V(ctx->Color.ColorMask, save->ColorMask)) { _mesa_ColorMask(save->ColorMask[0], save->ColorMask[1], save->ColorMask[2], save->ColorMask[3]); } } if (state & MESA_META_DEPTH_TEST) { if (ctx->Depth.Test != save->Depth.Test) _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test); _mesa_DepthFunc(save->Depth.Func); _mesa_DepthMask(save->Depth.Mask); } if (state & MESA_META_FOG) { _mesa_set_enable(ctx, GL_FOG, save->Fog); } if (state & MESA_META_PIXEL_STORE) { ctx->Pack = save->Pack; ctx->Unpack = save->Unpack; } if (state & MESA_META_PIXEL_TRANSFER) { ctx->Pixel.RedScale = save->RedScale; ctx->Pixel.RedBias = save->RedBias; ctx->Pixel.GreenScale = save->GreenScale; ctx->Pixel.GreenBias = save->GreenBias; ctx->Pixel.BlueScale = save->BlueScale; ctx->Pixel.BlueBias = save->BlueBias; ctx->Pixel.AlphaScale = save->AlphaScale; ctx->Pixel.AlphaBias = save->AlphaBias; ctx->Pixel.MapColorFlag = save->MapColorFlag; /* XXX more state */ ctx->NewState |=_NEW_PIXEL; } if (state & MESA_META_RASTERIZATION) { _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset); _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull); } if (state & MESA_META_SCISSOR) { _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled); _mesa_Scissor(save->Scissor.X, save->Scissor.Y, save->Scissor.Width, save->Scissor.Height); } if (state & MESA_META_STENCIL_TEST) { const struct gl_stencil_attrib *stencil = &save->Stencil; _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); } if (state & MESA_META_TEXTURE) { GLuint tgt; /* restore texenv for unit[0] */ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); /* restore texture objects for unit[0] only */ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { if (ctx->Texture.Unit.CurrentTex[tgt] != save->CurrentTexture[tgt]) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); _mesa_reference_texobj(&ctx->Texture.Unit.CurrentTex[tgt], save->CurrentTexture[tgt]); } _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL); } /* Restore fixed function texture enables, texgen */ if (ctx->Texture.Unit.Enabled != save->TexEnabled) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); ctx->Texture.Unit.Enabled = save->TexEnabled; } if (ctx->Texture.Unit.TexGenEnabled != save->TexGenEnabled) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); ctx->Texture.Unit.TexGenEnabled = save->TexGenEnabled; } } if (state & MESA_META_TRANSFORM) { _mesa_MatrixMode(GL_TEXTURE); _mesa_LoadMatrixf(save->TextureMatrix); _mesa_MatrixMode(GL_MODELVIEW); _mesa_LoadMatrixf(save->ModelviewMatrix); _mesa_MatrixMode(GL_PROJECTION); _mesa_LoadMatrixf(save->ProjectionMatrix); _mesa_MatrixMode(save->MatrixMode); } if (state & MESA_META_CLIP) { if (save->ClipPlanesEnabled) { GLuint i; for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { if (save->ClipPlanesEnabled & (1 << i)) { _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE); } } } } if (state & MESA_META_VIEWPORT) { if (save->ViewportX != ctx->Viewport.X || save->ViewportY != ctx->Viewport.Y || save->ViewportW != ctx->Viewport.Width || save->ViewportH != ctx->Viewport.Height) { _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY, save->ViewportW, save->ViewportH); } _mesa_DepthRange(save->DepthNear, save->DepthFar); } /* misc */ if (save->Lighting) { _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE); } if (save->RasterDiscard) { _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE); } }
/** * Enter meta state. This is like a light-weight version of glPushAttrib * but it also resets most GL state back to default values. * * \param state bitmask of MESA_META_* flags indicating which attribute groups * to save and reset to their defaults */ void _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) { struct save_state *save; /* hope MAX_META_OPS_DEPTH is large enough */ assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH); save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++]; memset(save, 0, sizeof(*save)); save->SavedState = state; if (state & MESA_META_ALPHA_TEST) { save->AlphaEnabled = ctx->Color.AlphaEnabled; save->AlphaFunc = ctx->Color.AlphaFunc; save->AlphaRef = ctx->Color.AlphaRef; if (ctx->Color.AlphaEnabled) _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE); } if (state & MESA_META_BLEND) { save->BlendEnabled = ctx->Color.BlendEnabled; if (ctx->Color.BlendEnabled) { _mesa_set_enable(ctx, GL_BLEND, GL_FALSE); } save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled; if (ctx->Color.ColorLogicOpEnabled) _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE); } if (state & MESA_META_COLOR_MASK) { memcpy(save->ColorMask, ctx->Color.ColorMask, sizeof(ctx->Color.ColorMask)); if (!ctx->Color.ColorMask[0] || !ctx->Color.ColorMask[1] || !ctx->Color.ColorMask[2] || !ctx->Color.ColorMask[3]) _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } if (state & MESA_META_DEPTH_TEST) { save->Depth = ctx->Depth; /* struct copy */ if (ctx->Depth.Test) _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); } if (state & MESA_META_FOG) { save->Fog = ctx->Fog.Enabled; if (ctx->Fog.Enabled) _mesa_set_enable(ctx, GL_FOG, GL_FALSE); } if (state & MESA_META_PIXEL_STORE) { save->Pack = ctx->Pack; save->Unpack = ctx->Unpack; ctx->Pack = ctx->DefaultPacking; ctx->Unpack = ctx->DefaultPacking; } if (state & MESA_META_PIXEL_TRANSFER) { save->RedScale = ctx->Pixel.RedScale; save->RedBias = ctx->Pixel.RedBias; save->GreenScale = ctx->Pixel.GreenScale; save->GreenBias = ctx->Pixel.GreenBias; save->BlueScale = ctx->Pixel.BlueScale; save->BlueBias = ctx->Pixel.BlueBias; save->AlphaScale = ctx->Pixel.AlphaScale; save->AlphaBias = ctx->Pixel.AlphaBias; save->MapColorFlag = ctx->Pixel.MapColorFlag; ctx->Pixel.RedScale = 1.0F; ctx->Pixel.RedBias = 0.0F; ctx->Pixel.GreenScale = 1.0F; ctx->Pixel.GreenBias = 0.0F; ctx->Pixel.BlueScale = 1.0F; ctx->Pixel.BlueBias = 0.0F; ctx->Pixel.AlphaScale = 1.0F; ctx->Pixel.AlphaBias = 0.0F; ctx->Pixel.MapColorFlag = GL_FALSE; /* XXX more state */ ctx->NewState |=_NEW_PIXEL; } if (state & MESA_META_RASTERIZATION) { save->FrontPolygonMode = ctx->Polygon.FrontMode; save->BackPolygonMode = ctx->Polygon.BackMode; save->PolygonOffset = ctx->Polygon.OffsetFill; save->PolygonSmooth = ctx->Polygon.SmoothFlag; save->PolygonStipple = ctx->Polygon.StippleFlag; save->PolygonCull = ctx->Polygon.CullFlag; _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE); _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE); } if (state & MESA_META_SCISSOR) { save->Scissor = ctx->Scissor; /* struct copy */ _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE); } if (state & MESA_META_STENCIL_TEST) { save->Stencil = ctx->Stencil; /* struct copy */ if (ctx->Stencil.Enabled) _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE); /* NOTE: other stencil state not reset */ } if (state & MESA_META_TEXTURE) { GLuint tgt; save->EnvMode = ctx->Texture.Unit.EnvMode; /* Disable all texture units */ save->TexEnabled = ctx->Texture.Unit.Enabled; save->TexGenEnabled = ctx->Texture.Unit.TexGenEnabled; if (ctx->Texture.Unit.Enabled || ctx->Texture.Unit.TexGenEnabled) { _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); if (ctx->Extensions.ARB_texture_cube_map) _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); } /* save current texture objects for unit[0] only */ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { _mesa_reference_texobj(&save->CurrentTexture[tgt], ctx->Texture.Unit.CurrentTex[tgt]); } _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } if (state & MESA_META_TRANSFORM) { memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m, 16 * sizeof(GLfloat)); memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m, 16 * sizeof(GLfloat)); memcpy(save->TextureMatrix, ctx->TextureMatrixStack.Top->m, 16 * sizeof(GLfloat)); save->MatrixMode = ctx->Transform.MatrixMode; /* set 1:1 vertex:pixel coordinate transform */ _mesa_MatrixMode(GL_TEXTURE); _mesa_LoadIdentity(); _mesa_MatrixMode(GL_MODELVIEW); _mesa_LoadIdentity(); _mesa_MatrixMode(GL_PROJECTION); _mesa_LoadIdentity(); _mesa_Ortho(0.0, ctx->DrawBuffer->Width, 0.0, ctx->DrawBuffer->Height, -1.0, 1.0); } if (state & MESA_META_CLIP) { save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled; if (ctx->Transform.ClipPlanesEnabled) { GLuint i; for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE); } } } if (state & MESA_META_VIEWPORT) { /* save viewport state */ save->ViewportX = ctx->Viewport.X; save->ViewportY = ctx->Viewport.Y; save->ViewportW = ctx->Viewport.Width; save->ViewportH = ctx->Viewport.Height; /* set viewport to match window size */ if (ctx->Viewport.X != 0 || ctx->Viewport.Y != 0 || ctx->Viewport.Width != ctx->DrawBuffer->Width || ctx->Viewport.Height != ctx->DrawBuffer->Height) { _mesa_set_viewport(ctx, 0, 0, ctx->DrawBuffer->Width, ctx->DrawBuffer->Height); } /* save depth range state */ save->DepthNear = ctx->Viewport.Near; save->DepthFar = ctx->Viewport.Far; /* set depth range to default */ _mesa_DepthRange(0.0, 1.0); } if (state & MESA_META_SELECT_FEEDBACK) { save->RenderMode = ctx->RenderMode; if (ctx->RenderMode == GL_SELECT) { save->Select = ctx->Select; /* struct copy */ _mesa_RenderMode(GL_RENDER); } else if (ctx->RenderMode == GL_FEEDBACK) { save->Feedback = ctx->Feedback; /* struct copy */ _mesa_RenderMode(GL_RENDER); } } /* misc */ { save->Lighting = ctx->Light.Enabled; if (ctx->Light.Enabled) _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE); save->RasterDiscard = ctx->RasterDiscard; if (ctx->RasterDiscard) _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE); } }
/** * Try to do a color or depth glBlitFramebuffer using texturing. * * We can do this when the src renderbuffer is actually a texture, or when the * driver exposes BindRenderbufferTexImage(). */ static bool blitframebuffer_texture(struct gl_context *ctx, const struct gl_framebuffer *readFb, const struct gl_framebuffer *drawFb, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLenum filter, GLint flipX, GLint flipY, GLboolean glsl_version, GLboolean do_depth) { int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex; const struct gl_renderbuffer_attachment *readAtt = &readFb->Attachment[att_index]; struct blit_state *blit = &ctx->Meta->Blit; struct fb_tex_blit_state fb_tex_blit; const GLint dstX = MIN2(dstX0, dstX1); const GLint dstY = MIN2(dstY0, dstY1); const GLint dstW = abs(dstX1 - dstX0); const GLint dstH = abs(dstY1 - dstY0); const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); bool scaled_blit = false; struct gl_texture_object *texObj; GLuint srcLevel; GLenum target; struct gl_renderbuffer *rb = readAtt->Renderbuffer; struct temp_texture *meta_temp_texture; if (rb->NumSamples && !ctx->Extensions.ARB_texture_multisample) return false; _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit); if (readAtt->Texture && (readAtt->Texture->Target == GL_TEXTURE_2D || readAtt->Texture->Target == GL_TEXTURE_RECTANGLE || readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE || readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { /* If there's a texture attached of a type we can handle, then just use * it directly. */ srcLevel = readAtt->TextureLevel; texObj = readAtt->Texture; target = texObj->Target; } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) { if (!_mesa_meta_bind_rb_as_tex_image(ctx, rb, &fb_tex_blit.tempTex, &texObj, &target)) return false; srcLevel = 0; if (_mesa_is_winsys_fbo(readFb)) { GLint temp = srcY0; srcY0 = rb->Height - srcY1; srcY1 = rb->Height - temp; flipY = -flipY; } } else { GLenum tex_base_format; /* Fall back to doing a CopyTexSubImage to get the destination * renderbuffer into a texture. */ if (ctx->Meta->Blit.no_ctsi_fallback) return false; if (rb->NumSamples > 1) return false; if (do_depth) { meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx); tex_base_format = GL_DEPTH_COMPONENT; } else { meta_temp_texture = _mesa_meta_get_temp_texture(ctx); tex_base_format = _mesa_base_tex_format(ctx, rb->InternalFormat); } srcLevel = 0; target = meta_temp_texture->Target; texObj = _mesa_lookup_texture(ctx, meta_temp_texture->TexObj); if (texObj == NULL) { return false; } _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture, srcX0, srcY0, srcW, srcH, tex_base_format, filter); srcX0 = 0; srcY0 = 0; srcX1 = srcW; srcY1 = srcH; } fb_tex_blit.baseLevelSave = texObj->BaseLevel; fb_tex_blit.maxLevelSave = texObj->MaxLevel; fb_tex_blit.stencilSamplingSave = texObj->StencilSampling; scaled_blit = dstW != srcW || dstH != srcH; if (glsl_version) { setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, filter, scaled_blit, do_depth); } else { _mesa_meta_setup_ff_tnl_for_blit(ctx, &ctx->Meta->Blit.VAO, &ctx->Meta->Blit.buf_obj, 2); } /* printf("Blit from texture!\n"); printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); */ fb_tex_blit.sampler = _mesa_meta_setup_sampler(ctx, texObj, target, filter, srcLevel); /* Always do our blits with no net sRGB decode or encode. * * However, if both the src and dst can be srgb decode/encoded, enable them * so that we do any blending (from scaling or from MSAA resolves) in the * right colorspace. * * Our choice of not doing any net encode/decode is from the GL 3.0 * specification: * * "Blit operations bypass the fragment pipeline. The only fragment * operations which affect a blit are the pixel ownership test and the * scissor test." * * The GL 4.4 specification disagrees and says that the sRGB part of the * fragment pipeline applies, but this was found to break applications. */ if (ctx->Extensions.EXT_texture_sRGB_decode) { if (_mesa_get_format_color_encoding(rb->Format) == GL_SRGB && drawFb->Visual.sRGBCapable) { _mesa_SamplerParameteri(fb_tex_blit.sampler, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); _mesa_set_framebuffer_srgb(ctx, GL_TRUE); } else { _mesa_SamplerParameteri(fb_tex_blit.sampler, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); /* set_framebuffer_srgb was set by _mesa_meta_begin(). */ } } if (!glsl_version) { _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); _mesa_set_enable(ctx, target, GL_TRUE); } /* Prepare vertex data (the VBO was previously created and bound) */ { struct vertex verts[4]; GLfloat s0, t0, s1, t1; if (target == GL_TEXTURE_2D) { const struct gl_texture_image *texImage = _mesa_select_tex_image(texObj, target, srcLevel); s0 = srcX0 / (float) texImage->Width; s1 = srcX1 / (float) texImage->Width; t0 = srcY0 / (float) texImage->Height; t1 = srcY1 / (float) texImage->Height; } else { assert(target == GL_TEXTURE_RECTANGLE_ARB || target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY); s0 = (float) srcX0; s1 = (float) srcX1; t0 = (float) srcY0; t1 = (float) srcY1; } /* Silence valgrind warnings about reading uninitialized stack. */ memset(verts, 0, sizeof(verts)); /* setup vertex positions */ verts[0].x = -1.0F * flipX; verts[0].y = -1.0F * flipY; verts[1].x = 1.0F * flipX; verts[1].y = -1.0F * flipY; verts[2].x = 1.0F * flipX; verts[2].y = 1.0F * flipY; verts[3].x = -1.0F * flipX; verts[3].y = 1.0F * flipY; verts[0].tex[0] = s0; verts[0].tex[1] = t0; verts[0].tex[2] = readAtt->Zoffset; verts[1].tex[0] = s1; verts[1].tex[1] = t0; verts[1].tex[2] = readAtt->Zoffset; verts[2].tex[0] = s1; verts[2].tex[1] = t1; verts[2].tex[2] = readAtt->Zoffset; verts[3].tex[0] = s0; verts[3].tex[1] = t1; verts[3].tex[2] = readAtt->Zoffset; _mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts, __func__); } /* setup viewport */ _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth); _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth); _mesa_DepthMask(do_depth); _mesa_DepthFunc(GL_ALWAYS); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit); return true; }
void GLAPIENTRY _mesa_ViewportIndexedfv_no_error(GLuint index, const GLfloat *v) { GET_CURRENT_CONTEXT(ctx); _mesa_set_viewport(ctx, index, v[0], v[1], v[2], v[3]); }
/** * Called via ctx->Driver.GenerateMipmap() * Note: We don't yet support 3D textures, 1D/2D array textures or texture * borders. */ void _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; struct vertex verts[4]; const GLuint baseLevel = texObj->BaseLevel; const GLuint maxLevel = texObj->MaxLevel; const GLint maxLevelSave = texObj->MaxLevel; const GLboolean genMipmapSave = texObj->GenerateMipmap; const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit; const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && ctx->Extensions.ARB_fragment_shader; GLenum faceTarget; GLuint dstLevel; GLuint samplerSave; GLint swizzle[4]; GLboolean swizzleSaved = GL_FALSE; if (fallback_required(ctx, target, texObj)) { _mesa_generate_mipmap(ctx, target, texObj); return; } if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) { faceTarget = target; target = GL_TEXTURE_CUBE_MAP; } else { faceTarget = target; } _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS); /* Choose between glsl version and fixed function version of * GenerateMipmap function. */ if (use_glsl_version) { _mesa_meta_setup_vertex_objects(&mipmap->VAO, &mipmap->VBO, true, 2, 4, 0); _mesa_meta_setup_blit_shader(ctx, target, false, &mipmap->shaders); } else { _mesa_meta_setup_ff_tnl_for_blit(&mipmap->VAO, &mipmap->VBO, 3); _mesa_set_enable(ctx, target, GL_TRUE); } samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; if (currentTexUnitSave != 0) glBindTexture(target, texObj->Name); if (!mipmap->Sampler) { glGenSamplers(1, &mipmap->Sampler); glBindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler); glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); /* We don't want to encode or decode sRGB values; treat them as linear. * This is not technically correct for GLES3 but we don't get any API * error at the moment. */ if (ctx->Extensions.EXT_texture_sRGB_decode) { glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); } } else { glBindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler); } assert(mipmap->FBO != 0); glBindFramebuffer(GL_FRAMEBUFFER, mipmap->FBO); glTexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); // if (texObj->_Swizzle != SWIZZLE_NOOP) { // static const GLint swizzleNoop[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; // memcpy(swizzle, texObj->Swizzle, sizeof(swizzle)); // swizzleSaved = GL_TRUE; // glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzleNoop); // } /* Silence valgrind warnings about reading uninitialized stack. */ memset(verts, 0, sizeof(verts)); /* setup vertex positions */ verts[0].x = -1.0F; verts[0].y = -1.0F; verts[1].x = 1.0F; verts[1].y = -1.0F; verts[2].x = 1.0F; verts[2].y = 1.0F; verts[3].x = -1.0F; verts[3].y = 1.0F; /* texture is already locked, unlock now */ _mesa_unlock_texture(ctx, texObj); for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) { const struct gl_texture_image *srcImage; struct gl_texture_image *dstImage; const GLuint srcLevel = dstLevel - 1; GLuint layer; GLsizei srcWidth, srcHeight, srcDepth; GLsizei dstWidth, dstHeight, dstDepth; srcImage = _mesa_select_tex_image(texObj, faceTarget, srcLevel); assert(srcImage->Border == 0); /* src size */ srcWidth = srcImage->Width; if (target == GL_TEXTURE_1D_ARRAY) { srcHeight = 1; srcDepth = srcImage->Height; } else { srcHeight = srcImage->Height; srcDepth = srcImage->Depth; } /* new dst size */ dstWidth = minify(srcWidth, 1); dstHeight = minify(srcHeight, 1); // dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth; dstDepth = srcDepth; if (dstWidth == srcWidth && dstHeight == srcHeight && dstDepth == srcDepth) { /* all done */ break; } /* Allocate storage for the destination mipmap image(s) */ /* Set MaxLevel large enough to hold the new level when we allocate it */ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel); if (!prepare_mipmap_level(ctx, texObj, dstLevel, dstWidth, dstHeight, dstDepth, srcImage->InternalFormat, srcImage->TexFormat)) { /* All done. We either ran out of memory or we would go beyond the * last valid level of an immutable texture if we continued. */ break; } dstImage = _mesa_select_tex_image(texObj, faceTarget, dstLevel); /* limit minification to src level */ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); /* setup viewport */ _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight); glDrawBuffer(GL_COLOR_ATTACHMENT0); for (layer = 0; layer < dstDepth; ++layer) { /* Setup texture coordinates */ _mesa_meta_setup_texture_coords(faceTarget, layer, 0, 0, 1, /* width, height never used here */ verts[0].tex, verts[1].tex, verts[2].tex, verts[3].tex); /* upload vertex data */ glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW); _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstImage, layer); /* sanity check */ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { _mesa_problem(ctx, "Unexpected incomplete framebuffer in " "_mesa_meta_GenerateMipmap()"); break; } assert(dstWidth == ctx->DrawBuffer->Width); if (target == GL_TEXTURE_1D_ARRAY) { assert(dstHeight == 1); } else { assert(dstHeight == ctx->DrawBuffer->Height); } glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } _mesa_lock_texture(ctx, texObj); /* relock */ glBindSampler(ctx->Texture.CurrentUnit, samplerSave); _mesa_meta_end(ctx); glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); if (genMipmapSave) glTexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave); // if (swizzleSaved) // glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle); }
/** * Called via ctx->Driver.GenerateMipmap() * Note: We don't yet support 3D textures, or texture borders. */ void _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; struct vertex verts[4]; const GLuint baseLevel = texObj->BaseLevel; const GLuint maxLevel = texObj->MaxLevel; const GLint maxLevelSave = texObj->MaxLevel; const GLboolean genMipmapSave = texObj->GenerateMipmap; const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && ctx->Extensions.ARB_fragment_shader; GLenum faceTarget; GLuint dstLevel; struct gl_sampler_object *samp_obj_save = NULL; GLint swizzle[4]; GLboolean swizzleSaved = GL_FALSE; /* GLint so the compiler won't complain about type signedness mismatch in * the calls to _mesa_texture_parameteriv below. */ static const GLint always_false = GL_FALSE; static const GLint always_true = GL_TRUE; if (fallback_required(ctx, target, texObj)) { _mesa_generate_mipmap(ctx, target, texObj); return; } if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) { faceTarget = target; target = GL_TEXTURE_CUBE_MAP; } else { faceTarget = target; } _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS); _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); /* Choose between glsl version and fixed function version of * GenerateMipmap function. */ if (use_glsl_version) { _mesa_meta_setup_vertex_objects(ctx, &mipmap->VAO, &mipmap->buf_obj, true, 2, 4, 0); _mesa_meta_setup_blit_shader(ctx, target, false, &mipmap->shaders); } else { _mesa_meta_setup_ff_tnl_for_blit(ctx, &mipmap->VAO, &mipmap->buf_obj, 3); _mesa_set_enable(ctx, target, GL_TRUE); } _mesa_reference_sampler_object(ctx, &samp_obj_save, ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler); /* We may have been called from glGenerateTextureMipmap with CurrentUnit * still set to 0, so we don't know when we can skip binding the texture. * Assume that _mesa_BindTexture will be fast if we're rebinding the same * texture. */ _mesa_BindTexture(target, texObj->Name); if (mipmap->samp_obj == NULL) { mipmap->samp_obj = ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF); if (mipmap->samp_obj == NULL) { /* This is a bit lazy. Flag out of memory, and then don't bother to * clean up. Once out of memory is flagged, the only realistic next * move is to destroy the context. That will trigger all the right * clean up. */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenerateMipmap"); return; } _mesa_set_sampler_filters(ctx, mipmap->samp_obj, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR); _mesa_set_sampler_wrap(ctx, mipmap->samp_obj, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); /* We don't want to encode or decode sRGB values; treat them as linear. */ _mesa_set_sampler_srgb_decode(ctx, mipmap->samp_obj, GL_SKIP_DECODE_EXT); } _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, mipmap->samp_obj); assert(mipmap->fb != NULL); _mesa_bind_framebuffers(ctx, mipmap->fb, mipmap->fb); _mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_false, false); if (texObj->_Swizzle != SWIZZLE_NOOP) { static const GLint swizzleNoop[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; memcpy(swizzle, texObj->Swizzle, sizeof(swizzle)); swizzleSaved = GL_TRUE; _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA, swizzleNoop, false); } /* Silence valgrind warnings about reading uninitialized stack. */ memset(verts, 0, sizeof(verts)); /* setup vertex positions */ verts[0].x = -1.0F; verts[0].y = -1.0F; verts[1].x = 1.0F; verts[1].y = -1.0F; verts[2].x = 1.0F; verts[2].y = 1.0F; verts[3].x = -1.0F; verts[3].y = 1.0F; /* texture is already locked, unlock now */ _mesa_unlock_texture(ctx, texObj); _mesa_prepare_mipmap_levels(ctx, texObj, baseLevel, maxLevel); for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) { const struct gl_texture_image *srcImage; struct gl_texture_image *dstImage; const GLuint srcLevel = dstLevel - 1; GLuint layer; GLsizei srcWidth, srcHeight, srcDepth; GLsizei dstWidth, dstHeight, dstDepth; srcImage = _mesa_select_tex_image(texObj, faceTarget, srcLevel); assert(srcImage->Border == 0); /* src size */ srcWidth = srcImage->Width; if (target == GL_TEXTURE_1D_ARRAY) { srcHeight = 1; srcDepth = srcImage->Height; } else { srcHeight = srcImage->Height; srcDepth = srcImage->Depth; } /* new dst size */ dstWidth = minify(srcWidth, 1); dstHeight = minify(srcHeight, 1); dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth; if (dstWidth == srcWidth && dstHeight == srcHeight && dstDepth == srcDepth) { /* all done */ break; } /* Allocate storage for the destination mipmap image(s) */ /* Set MaxLevel large enough to hold the new level when we allocate it */ _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, (GLint *) &dstLevel, false); dstImage = _mesa_select_tex_image(texObj, faceTarget, dstLevel); /* All done. We either ran out of memory or we would go beyond the last * valid level of an immutable texture if we continued. */ if (dstImage == NULL) break; /* limit minification to src level */ _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, (GLint *) &srcLevel, false); /* setup viewport */ _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight); _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); for (layer = 0; layer < dstDepth; ++layer) { /* Setup texture coordinates */ _mesa_meta_setup_texture_coords(faceTarget, layer, 0, 0, /* xoffset, yoffset */ srcWidth, srcHeight, /* img size */ srcWidth, srcHeight, srcDepth, verts[0].tex, verts[1].tex, verts[2].tex, verts[3].tex); /* upload vertex data */ _mesa_buffer_data(ctx, mipmap->buf_obj, GL_NONE, sizeof(verts), verts, GL_DYNAMIC_DRAW, __func__); _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, dstImage, layer); /* sanity check */ if (_mesa_check_framebuffer_status(ctx, ctx->DrawBuffer) != GL_FRAMEBUFFER_COMPLETE) { _mesa_problem(ctx, "Unexpected incomplete framebuffer in " "_mesa_meta_GenerateMipmap()"); break; } assert(dstWidth == ctx->DrawBuffer->Width); if (target == GL_TEXTURE_1D_ARRAY) { assert(dstHeight == 1); } else { assert(dstHeight == ctx->DrawBuffer->Height); } _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } } _mesa_lock_texture(ctx, texObj); /* relock */ _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj_save); _mesa_reference_sampler_object(ctx, &samp_obj_save, NULL); _mesa_meta_end(ctx); _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, &maxLevelSave, false); if (genMipmapSave) _mesa_texture_parameteriv(ctx, texObj, GL_GENERATE_MIPMAP, &always_true, false); if (swizzleSaved) _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_SWIZZLE_RGBA, swizzle, false); }
BOOL sw_SetContext(struct wgl_dc_data* dc_data, DHGLRC dhglrc) { struct sw_context* sw_ctx = (struct sw_context*)dhglrc; struct sw_framebuffer* fb = dc_data->sw_data; UINT width, height; /* Update state */ sw_update_state(&sw_ctx->mesa, 0); /* Get framebuffer size */ if(dc_data->flags & WGL_DC_OBJ_DC) { HWND hwnd = dc_data->owner.hwnd; RECT client_rect; if(!hwnd) { ERR("Physical DC without a window!\n"); return FALSE; } if(!GetClientRect(hwnd, &client_rect)) { ERR("GetClientRect failed!\n"); return FALSE; } /* This is a physical DC. Setup the hook */ sw_ctx->hook = SetWindowsHookEx(WH_CALLWNDPROC, sw_call_window_proc, NULL, GetCurrentThreadId()); /* Calculate width & height */ width = client_rect.right - client_rect.left; height = client_rect.bottom - client_rect.top; } else /* OBJ_MEMDC */ { BITMAP bm; HBITMAP hbmp; HDC hdc = dc_data->owner.hdc; if(fb->flags & SW_FB_DOUBLEBUFFERED) { ERR("Memory DC called with a double buffered format.\n"); return FALSE; } hbmp = GetCurrentObject( hdc, OBJ_BITMAP ); if(!hbmp) { ERR("No Bitmap!\n"); return FALSE; } if(GetObject(hbmp, sizeof(bm), &bm) == 0) { ERR("GetObject failed!\n"); return FALSE; } width = bm.bmWidth; height = bm.bmHeight; } if(!width) width = 1; if(!height) height = 1; fb->bmi.bmiHeader.biWidth = width; fb->bmi.bmiHeader.biHeight = height; /* Also make the mesa context current to mesa */ if(!_mesa_make_current(&sw_ctx->mesa, fb->gl_buffer, fb->gl_buffer)) { ERR("_mesa_make_current filaed!\n"); return FALSE; } /* Set the viewport if this is the first time we initialize this context */ if(sw_ctx->mesa.Viewport.X == 0 && sw_ctx->mesa.Viewport.Y == 0 && sw_ctx->mesa.Viewport.Width == 0 && sw_ctx->mesa.Viewport.Height == 0) { _mesa_set_viewport(&sw_ctx->mesa, 0, 0, width, height); } /* update the framebuffer size */ _mesa_resize_framebuffer(&sw_ctx->mesa, fb->gl_buffer, width, height); /* We're good */ return TRUE; }