#include "main/macros.h"
#include "main/matrix.h"
#include "main/polygon.h"
+#include "main/readpix.h"
#include "main/scissor.h"
#include "main/shaders.h"
#include "main/stencil.h"
/** META_FOG */
GLboolean Fog;
- /** META_PIXELSTORE */
- /* XXX / TO-DO */
+ /** META_PIXEL_STORE */
+ struct gl_pixelstore_attrib Pack, Unpack;
/** META_RASTERIZATION */
GLenum FrontPolygonMode, BackPolygonMode;
{
GLuint ArrayObj;
GLuint VBO;
- GLfloat verts[4][4]; /**< four verts of X,Y,S,T */
+ GLuint DepthFP;
};
{
GLuint ArrayObj;
GLuint VBO;
- GLfloat verts[4][7]; /**< four verts of X,Y,Z,R,G,B,A */
};
{
GLuint ArrayObj;
GLuint VBO;
- GLfloat verts[4][5]; /**< four verts of X,Y,Z,S,T */
};
{
GLuint ArrayObj;
GLuint VBO;
- GLfloat verts[4][5]; /**< four verts of X,Y,Z,S,T */
GLuint StencilFP; /**< Fragment program for drawing stencil images */
GLuint DepthFP; /**< Fragment program for drawing depth images */
* still get freed by _mesa_free_context_data().
*/
- if (meta->TempTex.TexObj) {
- _mesa_DeleteTextures(1, &meta->TempTex.TexObj);
- }
+ _mesa_DeleteTextures(1, &meta->TempTex.TexObj);
- if (meta->Blit.VBO) {
- _mesa_DeleteBuffersARB(1, & meta->Blit.VBO);
- _mesa_DeleteVertexArraysAPPLE(1, &meta->Blit.ArrayObj);
- }
+ /* glBlitFramebuffer */
+ _mesa_DeleteBuffersARB(1, & meta->Blit.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->Blit.ArrayObj);
+ _mesa_DeletePrograms(1, &meta->Blit.DepthFP);
- if (meta->Clear.VBO) {
- _mesa_DeleteBuffersARB(1, & meta->Clear.VBO);
- _mesa_DeleteVertexArraysAPPLE(1, &meta->Clear.ArrayObj);
- }
+ /* glClear */
+ _mesa_DeleteBuffersARB(1, & meta->Clear.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->Clear.ArrayObj);
- if (meta->CopyPix.VBO) {
- _mesa_DeleteBuffersARB(1, & meta->CopyPix.VBO);
- _mesa_DeleteVertexArraysAPPLE(1, &meta->CopyPix.ArrayObj);
- }
+ /* glCopyPixels */
+ _mesa_DeleteBuffersARB(1, & meta->CopyPix.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->CopyPix.ArrayObj);
- if (meta->DrawPix.VBO) {
- _mesa_DeleteBuffersARB(1, & meta->DrawPix.VBO);
- _mesa_DeleteVertexArraysAPPLE(1, &meta->DrawPix.ArrayObj);
- }
+ /* glDrawPixels */
+ _mesa_DeleteBuffersARB(1, & meta->DrawPix.VBO);
+ _mesa_DeleteVertexArraysAPPLE(1, &meta->DrawPix.ArrayObj);
+ _mesa_DeletePrograms(1, &meta->DrawPix.DepthFP);
+ _mesa_DeletePrograms(1, &meta->DrawPix.StencilFP);
}
_mesa_free(ctx->Meta);
_mesa_set_enable(ctx, GL_FOG, GL_FALSE);
}
+ if (state & META_PIXEL_STORE) {
+ save->Pack = ctx->Pack;
+ save->Unpack = ctx->Unpack;
+ ctx->Pack = ctx->DefaultPacking;
+ ctx->Unpack = ctx->DefaultPacking;
+ }
+
if (state & META_RASTERIZATION) {
save->FrontPolygonMode = ctx->Polygon.FrontMode;
save->BackPolygonMode = ctx->Polygon.BackMode;
_mesa_set_enable(ctx, GL_FOG, save->Fog);
}
+ if (state & META_PIXEL_STORE) {
+ ctx->Pack = save->Pack;
+ ctx->Unpack = save->Unpack;
+ }
+
if (state & META_RASTERIZATION) {
_mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode);
_mesa_PolygonMode(GL_BACK, save->BackPolygonMode);
{
GLboolean newTex = GL_FALSE;
- if (1|| width > tex->Width ||
+ if (width > tex->Width ||
height > tex->Height ||
intFormat != tex->IntFormat) {
/* alloc new texture (larger or different format) */
+/**
+ * One-time init for drawing depth pixels.
+ */
+static void
+init_blit_depth_pixels(GLcontext *ctx)
+{
+ static const char *program =
+ "!!ARBfp1.0\n"
+ "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n"
+ "END \n";
+ char program2[200];
+ struct blit_state *blit = &ctx->Meta->Blit;
+ struct temp_texture *tex = get_temp_texture(ctx);
+ const char *texTarget;
+
+ assert(blit->DepthFP == 0);
+
+ /* replace %s with "RECT" or "2D" */
+ assert(strlen(program) + 4 < sizeof(program2));
+ if (tex->Target == GL_TEXTURE_RECTANGLE)
+ texTarget = "RECT";
+ else
+ texTarget = "2D";
+ _mesa_snprintf(program2, sizeof(program2), program, texTarget);
+
+ _mesa_GenPrograms(1, &blit->DepthFP);
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+ strlen(program2), (const GLubyte *) program2);
+}
+
+
/**
* Meta implementation of ctx->Driver.BlitFramebuffer() in terms
* of texture mapping and polygon rendering.
const GLint srcH = abs(srcY1 - srcY0);
const GLboolean srcFlipX = srcX1 < srcX0;
const GLboolean srcFlipY = srcY1 < srcY0;
+ GLfloat verts[4][4]; /* four verts of X,Y,S,T */
GLboolean newTex;
if (srcW > maxTexSize || srcH > maxTexSize) {
/* create vertex array buffer */
_mesa_GenBuffersARB(1, &blit->VBO);
_mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(blit->verts),
- blit->verts, GL_STREAM_DRAW_ARB);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
/* setup vertex arrays */
- _mesa_VertexPointer(2, GL_FLOAT, 4 * sizeof(GLfloat),
- (void*) (0 * sizeof(GLfloat)));
- _mesa_TexCoordPointer(2, GL_FLOAT, 4 * sizeof(GLfloat),
+ _mesa_VertexPointer(2, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(verts[0]),
(void *) (2 * sizeof(GLfloat)));
_mesa_EnableClientState(GL_VERTEX_ARRAY);
_mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
/* vertex positions/texcoords (after texture allocation!) */
{
- blit->verts[0][0] = (GLfloat) dstX0;
- blit->verts[0][1] = (GLfloat) dstY0;
- blit->verts[1][0] = (GLfloat) dstX1;
- blit->verts[1][1] = (GLfloat) dstY0;
- blit->verts[2][0] = (GLfloat) dstX1;
- blit->verts[2][1] = (GLfloat) dstY1;
- blit->verts[3][0] = (GLfloat) dstX0;
- blit->verts[3][1] = (GLfloat) dstY1;
-
- blit->verts[0][2] = 0.0F;
- blit->verts[0][3] = 0.0F;
- blit->verts[1][2] = tex->Sright;
- blit->verts[1][3] = 0.0F;
- blit->verts[2][2] = tex->Sright;
- blit->verts[2][3] = tex->Ttop;
- blit->verts[3][2] = 0.0F;
- blit->verts[3][3] = tex->Ttop;
+ verts[0][0] = (GLfloat) dstX0;
+ verts[0][1] = (GLfloat) dstY0;
+ verts[1][0] = (GLfloat) dstX1;
+ verts[1][1] = (GLfloat) dstY0;
+ verts[2][0] = (GLfloat) dstX1;
+ verts[2][1] = (GLfloat) dstY1;
+ verts[3][0] = (GLfloat) dstX0;
+ verts[3][1] = (GLfloat) dstY1;
+
+ verts[0][2] = 0.0F;
+ verts[0][3] = 0.0F;
+ verts[1][2] = tex->Sright;
+ verts[1][3] = 0.0F;
+ verts[2][2] = tex->Sright;
+ verts[2][3] = tex->Ttop;
+ verts[3][2] = 0.0F;
+ verts[3][3] = tex->Ttop;
/* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0,
- sizeof(blit->verts), blit->verts);
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
}
_mesa_Enable(tex->Target);
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
mask &= ~GL_COLOR_BUFFER_BIT;
}
+
if (mask & GL_DEPTH_BUFFER_BIT) {
- /* XXX todo (need fragment shader) */
+ GLuint *tmp = (GLuint *) _mesa_malloc(srcW * srcH * sizeof(GLuint));
+ if (tmp) {
+ if (!blit->DepthFP)
+ init_blit_depth_pixels(ctx);
+
+ /* maybe change tex format here */
+ newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT);
+
+ _mesa_ReadPixels(srcX, srcY, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ setup_drawpix_texture(tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
+ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
+
+ _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
+ _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE);
+ _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_ALWAYS);
+ _mesa_DepthMask(GL_TRUE);
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+
+ _mesa_free(tmp);
+ }
}
+
if (mask & GL_STENCIL_BUFFER_BIT) {
/* XXX can't easily do stencil */
}
_mesa_meta_end(ctx);
- /* XXX, TO-DO: try to handle these cases above! */
- if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
+ if (mask) {
_swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1, mask, filter);
}
_mesa_meta_clear(GLcontext *ctx, GLbitfield buffers)
{
struct clear_state *clear = &ctx->Meta->Clear;
- GLbitfield metaSave = META_ALL - META_SCISSOR; /* all but scissor */
+ GLfloat verts[4][7]; /* four verts of X,Y,Z,R,G,B,A */
+ /* save all state but scissor, pixel pack/unpack */
+ GLbitfield metaSave = META_ALL - META_SCISSOR - META_PIXEL_STORE;
if (buffers & BUFFER_BITS_COLOR) {
/* if clearing color buffers, don't save/restore colormask */
/* create vertex array buffer */
_mesa_GenBuffersARB(1, &clear->VBO);
_mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(clear->verts),
- clear->verts, GL_STREAM_DRAW_ARB);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
/* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, 7 * sizeof(GLfloat), (void *) 0);
- _mesa_ColorPointer(4, GL_FLOAT, 7 * sizeof(GLfloat),
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_ColorPointer(4, GL_FLOAT, sizeof(verts[0]),
(void *) (3 * sizeof(GLfloat)));
_mesa_EnableClientState(GL_VERTEX_ARRAY);
_mesa_EnableClientState(GL_COLOR_ARRAY);
const GLfloat z = 1.0 - 2.0 * ctx->Depth.Clear;
GLuint i;
- clear->verts[0][0] = x0;
- clear->verts[0][1] = y0;
- clear->verts[0][2] = z;
- clear->verts[1][0] = x1;
- clear->verts[1][1] = y0;
- clear->verts[1][2] = z;
- clear->verts[2][0] = x1;
- clear->verts[2][1] = y1;
- clear->verts[2][2] = z;
- clear->verts[3][0] = x0;
- clear->verts[3][1] = y1;
- clear->verts[3][2] = z;
+ verts[0][0] = x0;
+ verts[0][1] = y0;
+ verts[0][2] = z;
+ verts[1][0] = x1;
+ verts[1][1] = y0;
+ verts[1][2] = z;
+ verts[2][0] = x1;
+ verts[2][1] = y1;
+ verts[2][2] = z;
+ verts[3][0] = x0;
+ verts[3][1] = y1;
+ verts[3][2] = z;
/* vertex colors */
for (i = 0; i < 4; i++) {
- COPY_4FV(&clear->verts[i][3], ctx->Color.ClearColor);
+ COPY_4FV(&verts[i][3], ctx->Color.ClearColor);
}
/* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0,
- sizeof(clear->verts), clear->verts);
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
}
/* draw quad */
{
struct copypix_state *copypix = &ctx->Meta->CopyPix;
struct temp_texture *tex = get_temp_texture(ctx);
+ GLfloat verts[4][5]; /* four verts of X,Y,Z,S,T */
GLboolean newTex;
GLenum intFormat = GL_RGBA;
/* create vertex array buffer */
_mesa_GenBuffersARB(1, ©pix->VBO);
_mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(copypix->verts),
- copypix->verts, GL_STREAM_DRAW_ARB);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
/* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, sizeof(copypix->verts[0]),
- (void*) (0 * sizeof(GLfloat)));
- _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(copypix->verts[0]),
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(verts[0]),
(void *) (3 * sizeof(GLfloat)));
_mesa_EnableClientState(GL_VERTEX_ARRAY);
_mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY;
const GLfloat z = ctx->Current.RasterPos[2];
- copypix->verts[0][0] = dstX0;
- copypix->verts[0][1] = dstY0;
- copypix->verts[0][2] = z;
- copypix->verts[0][3] = 0.0F;
- copypix->verts[0][4] = 0.0F;
- copypix->verts[1][0] = dstX1;
- copypix->verts[1][1] = dstY0;
- copypix->verts[1][2] = z;
- copypix->verts[1][3] = tex->Sright;
- copypix->verts[1][4] = 0.0F;
- copypix->verts[2][0] = dstX1;
- copypix->verts[2][1] = dstY1;
- copypix->verts[2][2] = z;
- copypix->verts[2][3] = tex->Sright;
- copypix->verts[2][4] = tex->Ttop;
- copypix->verts[3][0] = dstX0;
- copypix->verts[3][1] = dstY1;
- copypix->verts[3][2] = z;
- copypix->verts[3][3] = 0.0F;
- copypix->verts[3][4] = tex->Ttop;
+ verts[0][0] = dstX0;
+ verts[0][1] = dstY0;
+ verts[0][2] = z;
+ verts[0][3] = 0.0F;
+ verts[0][4] = 0.0F;
+ verts[1][0] = dstX1;
+ verts[1][1] = dstY0;
+ verts[1][2] = z;
+ verts[1][3] = tex->Sright;
+ verts[1][4] = 0.0F;
+ verts[2][0] = dstX1;
+ verts[2][1] = dstY1;
+ verts[2][2] = z;
+ verts[2][3] = tex->Sright;
+ verts[2][4] = tex->Ttop;
+ verts[3][0] = dstX0;
+ verts[3][1] = dstY1;
+ verts[3][2] = z;
+ verts[3][3] = 0.0F;
+ verts[3][4] = tex->Ttop;
/* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0,
- sizeof(copypix->verts), copypix->verts);
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
}
/* Alloc/setup texture */
struct drawpix_state *drawpix = &ctx->Meta->DrawPix;
struct temp_texture *tex = get_temp_texture(ctx);
const struct gl_pixelstore_attrib unpackSave = ctx->Unpack;
+ const GLuint origStencilMask = ctx->Stencil.WriteMask[0];
+ GLfloat verts[4][5]; /* four verts of X,Y,Z,S,T */
GLenum texIntFormat;
GLboolean fallback, newTex;
GLbitfield metaExtraSave = 0x0;
if (_mesa_is_color_format(format)) {
/* use more compact format when possible */
- if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA)
+ /* XXX disable special case for GL_LUMINANCE for now to work around
+ * apparent i965 driver bug (see bug #23670).
+ */
+ if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA)
texIntFormat = format;
else
texIntFormat = GL_RGBA;
/* create vertex array buffer */
_mesa_GenBuffersARB(1, &drawpix->VBO);
_mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawpix->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(drawpix->verts),
- drawpix->verts, GL_STREAM_DRAW_ARB);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ NULL, GL_DYNAMIC_DRAW_ARB);
/* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, sizeof(drawpix->verts[0]),
- (void*) (0 * sizeof(GLfloat)));
- _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(drawpix->verts[0]),
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(verts[0]),
+ (void *) (0 * sizeof(GLfloat)));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(verts[0]),
(void *) (3 * sizeof(GLfloat)));
_mesa_EnableClientState(GL_VERTEX_ARRAY);
_mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat y1 = y + height * ctx->Pixel.ZoomY;
const GLfloat z = ctx->Current.RasterPos[2];
- drawpix->verts[0][0] = x0;
- drawpix->verts[0][1] = y0;
- drawpix->verts[0][2] = z;
- drawpix->verts[0][3] = 0.0F;
- drawpix->verts[0][4] = 0.0F;
- drawpix->verts[1][0] = x1;
- drawpix->verts[1][1] = y0;
- drawpix->verts[1][2] = z;
- drawpix->verts[1][3] = tex->Sright;
- drawpix->verts[1][4] = 0.0F;
- drawpix->verts[2][0] = x1;
- drawpix->verts[2][1] = y1;
- drawpix->verts[2][2] = z;
- drawpix->verts[2][3] = tex->Sright;
- drawpix->verts[2][4] = tex->Ttop;
- drawpix->verts[3][0] = x0;
- drawpix->verts[3][1] = y1;
- drawpix->verts[3][2] = z;
- drawpix->verts[3][3] = 0.0F;
- drawpix->verts[3][4] = tex->Ttop;
+ verts[0][0] = x0;
+ verts[0][1] = y0;
+ verts[0][2] = z;
+ verts[0][3] = 0.0F;
+ verts[0][4] = 0.0F;
+ verts[1][0] = x1;
+ verts[1][1] = y0;
+ verts[1][2] = z;
+ verts[1][3] = tex->Sright;
+ verts[1][4] = 0.0F;
+ verts[2][0] = x1;
+ verts[2][1] = y1;
+ verts[2][2] = z;
+ verts[2][3] = tex->Sright;
+ verts[2][4] = tex->Ttop;
+ verts[3][0] = x0;
+ verts[3][1] = y1;
+ verts[3][2] = z;
+ verts[3][3] = 0.0F;
+ verts[3][4] = tex->Ttop;
/* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0,
- sizeof(drawpix->verts), drawpix->verts);
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
}
/* set given unpack params */
for (bit = 0; bit < ctx->Visual.stencilBits; bit++) {
const GLuint mask = 1 << bit;
+ if (mask & origStencilMask) {
+ _mesa_StencilFunc(GL_ALWAYS, mask, mask);
+ _mesa_StencilMask(mask);
- _mesa_StencilFunc(GL_ALWAYS, mask, mask);
- _mesa_StencilMask(mask);
+ _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
+ 255.0 / mask, 0.5, 0.0, 0.0);
- _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
- 255.0 / mask, 0.5, 0.0, 0.0);
-
- _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
}
}
else if (_mesa_is_depth_format(format)) {