summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/common')
-rw-r--r--src/mesa/drivers/common/driverfuncs.c2
-rw-r--r--src/mesa/drivers/common/meta.c434
-rw-r--r--src/mesa/drivers/common/meta.h4
3 files changed, 371 insertions, 69 deletions
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index f09106b77c..0f8447cb70 100644
--- a/src/mesa/drivers/common/driverfuncs.c
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -106,7 +106,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
driver->CopyTexSubImage1D = _mesa_meta_CopyTexSubImage1D;
driver->CopyTexSubImage2D = _mesa_meta_CopyTexSubImage2D;
driver->CopyTexSubImage3D = _mesa_meta_CopyTexSubImage3D;
- driver->GenerateMipmap = _mesa_generate_mipmap;
+ driver->GenerateMipmap = _mesa_meta_GenerateMipmap;
driver->TestProxyTexImage = _mesa_test_proxy_teximage;
driver->CompressedTexImage1D = _mesa_store_compressed_teximage1d;
driver->CompressedTexImage2D = _mesa_store_compressed_teximage2d;
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index 532b2c9263..e1732241b3 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -55,6 +55,7 @@
#include "main/stencil.h"
#include "main/texobj.h"
#include "main/texenv.h"
+#include "main/texformat.h"
#include "main/teximage.h"
#include "main/texparam.h"
#include "main/texstate.h"
@@ -236,7 +237,6 @@ struct copypix_state
struct drawpix_state
{
GLuint ArrayObj;
- GLuint VBO;
GLuint StencilFP; /**< Fragment program for drawing stencil images */
GLuint DepthFP; /**< Fragment program for drawing depth images */
@@ -327,7 +327,6 @@ _mesa_meta_free(GLcontext *ctx)
_mesa_DeleteVertexArraysAPPLE(1, &meta->CopyPix.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);
@@ -976,7 +975,8 @@ setup_copypix_texture(struct temp_texture *tex,
* Setup/load texture for glDrawPixels.
*/
static void
-setup_drawpix_texture(struct temp_texture *tex,
+setup_drawpix_texture(GLcontext *ctx,
+ struct temp_texture *tex,
GLboolean newTex,
GLenum texIntFormat,
GLsizei width, GLsizei height,
@@ -997,9 +997,17 @@ setup_drawpix_texture(struct temp_texture *tex,
tex->Width, tex->Height, 0, format, type, pixels);
}
else {
+ struct gl_buffer_object *save_unpack_obj = NULL;
+
+ _mesa_reference_buffer_object(ctx, &save_unpack_obj,
+ ctx->Unpack.BufferObj);
+ _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
/* create empty texture */
_mesa_TexImage2D(tex->Target, 0, tex->IntFormat,
tex->Width, tex->Height, 0, format, type, NULL);
+ if (save_unpack_obj != NULL)
+ _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB,
+ save_unpack_obj->Name);
/* load image */
_mesa_TexSubImage2D(tex->Target, 0,
0, 0, width, height, format, type, pixels);
@@ -1047,6 +1055,124 @@ init_blit_depth_pixels(GLcontext *ctx)
/**
+ * Try to do a glBiltFramebuffer using no-copy texturing.
+ * We can do this when the src renderbuffer is actually a texture.
+ * But if the src buffer == dst buffer we cannot do this.
+ *
+ * \return new buffer mask indicating the buffers left to blit using the
+ * normal path.
+ */
+static GLbitfield
+blitframebuffer_texture(GLcontext *ctx,
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
+ const struct gl_framebuffer *readFb = ctx->ReadBuffer;
+ const struct gl_renderbuffer_attachment *drawAtt =
+ &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
+ const struct gl_renderbuffer_attachment *readAtt =
+ &readFb->Attachment[readFb->_ColorReadBufferIndex];
+
+ if (readAtt && readAtt->Texture) {
+ const struct gl_texture_object *texObj = readAtt->Texture;
+ const GLenum minFilterSave = texObj->MinFilter;
+ const GLenum magFilterSave = texObj->MagFilter;
+ const GLenum target = texObj->Target;
+
+ if (drawAtt->Texture == readAtt->Texture) {
+ /* Can't use same texture as both the source and dest. We need
+ * to handle overlapping blits and besides, some hw may not
+ * support this.
+ */
+ return mask;
+ }
+
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) {
+ /* Can't handle other texture types at this time */
+ return mask;
+ }
+
+ /*
+ printf("Blit from texture!\n");
+ printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt);
+ printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture);
+ */
+
+ /* Prepare src texture state */
+ _mesa_BindTexture(target, texObj->Name);
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
+ _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ /*_mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE);*/
+ _mesa_set_enable(ctx, target, GL_TRUE);
+
+ /* Prepare vertex data (the VBO was previously created and bound) */
+ {
+ struct vertex {
+ GLfloat x, y, s, t;
+ };
+ struct vertex verts[4];
+ GLfloat s0, t0, s1, t1;
+
+ if (target == GL_TEXTURE_2D) {
+ const struct gl_texture_image *texImage
+ = _mesa_select_tex_image(ctx, texObj, target,
+ readAtt->TextureLevel);
+ 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);
+ s0 = srcX0;
+ s1 = srcX1;
+ t0 = srcY0;
+ t1 = srcY1;
+ }
+
+ verts[0].x = (GLfloat) dstX0;
+ verts[0].y = (GLfloat) dstY0;
+ verts[1].x = (GLfloat) dstX1;
+ verts[1].y = (GLfloat) dstY0;
+ verts[2].x = (GLfloat) dstX1;
+ verts[2].y = (GLfloat) dstY1;
+ verts[3].x = (GLfloat) dstX0;
+ verts[3].y = (GLfloat) dstY1;
+
+ verts[0].s = s0;
+ verts[0].t = t0;
+ verts[1].s = s1;
+ verts[1].t = t0;
+ verts[2].s = s1;
+ verts[2].t = t1;
+ verts[3].s = s0;
+ verts[3].t = t1;
+
+ _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ }
+
+ _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ /* Restore texture's filter state, the texture binding will
+ * be restored by _mesa_meta_end().
+ */
+ _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
+
+ /* Done with color buffer */
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+ }
+
+ return mask;
+}
+
+
+/**
* Meta implementation of ctx->Driver.BlitFramebuffer() in terms
* of texture mapping and polygon rendering.
*/
@@ -1117,6 +1243,18 @@ _mesa_meta_BlitFramebuffer(GLcontext *ctx,
_mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO);
}
+ /* Try faster, direct texture approach first */
+ mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter);
+ if (mask == 0x0) {
+ _mesa_meta_end(ctx);
+ return;
+ }
+
+ /* Continue with "normal" approach which involves copying the src rect
+ * into a temporary texture and is "blitted" by drawing a textured quad.
+ */
+
newTex = alloc_texture(tex, srcW, srcH, GL_RGBA);
/* vertex positions/texcoords (after texture allocation!) */
@@ -1164,7 +1302,7 @@ _mesa_meta_BlitFramebuffer(GLcontext *ctx,
_mesa_ReadPixels(srcX, srcY, srcW, srcH,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
- setup_drawpix_texture(tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
+ setup_drawpix_texture(ctx, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp);
_mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP);
@@ -1585,6 +1723,7 @@ _mesa_meta_DrawPixels(GLcontext *ctx,
GLenum texIntFormat;
GLboolean fallback, newTex;
GLbitfield metaExtraSave = 0x0;
+ GLuint vbo;
/*
* Determine if we can do the glDrawPixels with texture mapping.
@@ -1664,30 +1803,6 @@ _mesa_meta_DrawPixels(GLcontext *ctx,
META_VIEWPORT |
metaExtraSave));
- if (drawpix->ArrayObj == 0) {
- /* one-time setup */
-
- /* create vertex array object */
- _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
- _mesa_BindVertexArray(drawpix->ArrayObj);
-
- /* create vertex array buffer */
- _mesa_GenBuffersARB(1, &drawpix->VBO);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawpix->VBO);
- _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
- NULL, GL_DYNAMIC_DRAW_ARB);
-
- /* setup vertex arrays */
- _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
- _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
- _mesa_EnableClientState(GL_VERTEX_ARRAY);
- _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- else {
- _mesa_BindVertexArray(drawpix->ArrayObj);
- _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawpix->VBO);
- }
-
newTex = alloc_texture(tex, width, height, texIntFormat);
/* vertex positions, texcoords (after texture allocation!) */
@@ -1718,10 +1833,25 @@ _mesa_meta_DrawPixels(GLcontext *ctx,
verts[3].z = z;
verts[3].s = 0.0F;
verts[3].t = tex->Ttop;
+ }
- /* upload new vertex data */
- _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
+ if (drawpix->ArrayObj == 0) {
+ /* one-time setup: create vertex array object */
+ _mesa_GenVertexArrays(1, &drawpix->ArrayObj);
}
+ _mesa_BindVertexArray(drawpix->ArrayObj);
+
+ /* create vertex array buffer */
+ _mesa_GenBuffersARB(1, &vbo);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts),
+ verts, GL_DYNAMIC_DRAW_ARB);
+
+ /* setup vertex arrays */
+ _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x));
+ _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s));
+ _mesa_EnableClientState(GL_VERTEX_ARRAY);
+ _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY);
/* set given unpack params */
ctx->Unpack = *unpack;
@@ -1735,7 +1865,7 @@ _mesa_meta_DrawPixels(GLcontext *ctx,
if (!drawpix->StencilFP)
init_draw_stencil_pixels(ctx);
- setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
GL_ALPHA, type, pixels);
_mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@@ -1778,20 +1908,22 @@ _mesa_meta_DrawPixels(GLcontext *ctx,
_mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0,
ctx->Current.RasterColor);
- setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
format, type, pixels);
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
else {
/* Drawing RGBA */
- setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
format, type, pixels);
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
_mesa_set_enable(ctx, tex->Target, GL_FALSE);
+ _mesa_DeleteBuffersARB(1, &vbo);
+
/* restore unpack params */
ctx->Unpack = unpackSave;
@@ -1931,7 +2063,7 @@ _mesa_meta_Bitmap(GLcontext *ctx,
_mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE);
_mesa_AlphaFunc(GL_GREATER, 0.0);
- setup_drawpix_texture(tex, newTex, texIntFormat, width, height,
+ setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height,
GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8);
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
@@ -1947,6 +2079,33 @@ _mesa_meta_Bitmap(GLcontext *ctx,
}
+/**
+ * Check if the call to _mesa_meta_GenerateMipmap() will require a
+ * software fallback. The fallback path will require that the texture
+ * images are mapped.
+ */
+GLboolean
+_mesa_meta_check_generate_mipmap_fallback(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj)
+{
+ struct gl_texture_image *baseImage =
+ _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
+
+ /* check for fallbacks */
+ if (!ctx->Extensions.EXT_framebuffer_object ||
+ target == GL_TEXTURE_3D ||
+ !baseImage ||
+ baseImage->IsCompressed) {
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Called via ctx->Driver.GenerateMipmap()
+ * Note: texture borders and 3D texture support not yet complete.
+ */
void
_mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj)
@@ -1960,13 +2119,18 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
const GLuint maxLevel = texObj->MaxLevel;
const GLenum minFilterSave = texObj->MinFilter;
const GLenum magFilterSave = texObj->MagFilter;
+ const GLint baseLevelSave = texObj->BaseLevel;
+ const GLint maxLevelSave = texObj->MaxLevel;
+ const GLboolean genMipmapSave = texObj->GenerateMipmap;
+ const GLenum wrapSSave = texObj->WrapS;
+ const GLenum wrapTSave = texObj->WrapT;
+ const GLenum wrapRSave = texObj->WrapR;
const GLuint fboSave = ctx->DrawBuffer->Name;
GLenum faceTarget;
- GLuint level;
+ GLuint dstLevel;
GLuint border = 0;
- /* check for fallbacks */
- if (!ctx->Extensions.EXT_framebuffer_object) {
+ if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
_mesa_generate_mipmap(ctx, target, texObj);
return;
}
@@ -2015,12 +2179,16 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
_mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
_mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
_mesa_set_enable(ctx, target, GL_TRUE);
/* setup texcoords once (XXX what about border?) */
switch (faceTarget) {
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- break;
+ case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
verts[0].s = 0.0F;
verts[0].t = 0.0F;
@@ -2035,63 +2203,180 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
verts[3].t = 1.0F;
verts[3].r = 0.0F;
break;
+ case GL_TEXTURE_3D:
+ abort();
+ break;
+ default:
+ /* cube face */
+ {
+ static const GLfloat st[4][2] = {
+ {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
+ };
+ GLuint i;
+
+ /* loop over quad verts */
+ for (i = 0; i < 4; i++) {
+ /* Compute sc = +/-scale and tc = +/-scale.
+ * Not +/-1 to avoid cube face selection ambiguity near the edges,
+ * though that can still sometimes happen with this scale factor...
+ */
+ const GLfloat scale = 0.9999f;
+ const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale;
+ const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale;
+
+ switch (faceTarget) {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ verts[i].s = 1.0f;
+ verts[i].t = -tc;
+ verts[i].r = -sc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ verts[i].s = -1.0f;
+ verts[i].t = -tc;
+ verts[i].r = sc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ verts[i].s = sc;
+ verts[i].t = 1.0f;
+ verts[i].r = tc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ verts[i].s = sc;
+ verts[i].t = -1.0f;
+ verts[i].r = -tc;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ verts[i].s = sc;
+ verts[i].t = -tc;
+ verts[i].r = 1.0f;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ verts[i].s = -sc;
+ verts[i].t = -tc;
+ verts[i].r = -1.0f;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
}
+ _mesa_set_enable(ctx, target, GL_TRUE);
+
+ /* texture is already locked, unlock now */
+ _mesa_unlock_texture(ctx, texObj);
- for (level = baseLevel + 1; level <= maxLevel; level++) {
+ for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
const struct gl_texture_image *srcImage;
- const GLuint srcLevel = level - 1;
- GLsizei srcWidth, srcHeight;
- GLsizei newWidth, newHeight;
+ const GLuint srcLevel = dstLevel - 1;
+ GLsizei srcWidth, srcHeight, srcDepth;
+ GLsizei dstWidth, dstHeight, dstDepth;
GLenum status;
- srcImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel);
+ srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel);
assert(srcImage->Border == 0); /* XXX we can fix this */
+ /* src size w/out border */
srcWidth = srcImage->Width - 2 * border;
srcHeight = srcImage->Height - 2 * border;
+ srcDepth = srcImage->Depth - 2 * border;
- newWidth = MAX2(1, srcWidth / 2) + 2 * border;
- newHeight = MAX2(1, srcHeight / 2) + 2 * border;
+ /* new dst size w/ border */
+ dstWidth = MAX2(1, srcWidth / 2) + 2 * border;
+ dstHeight = MAX2(1, srcHeight / 2) + 2 * border;
+ dstDepth = MAX2(1, srcDepth / 2) + 2 * border;
- if (newWidth == srcImage->Width && newHeight == srcImage->Height) {
- break;
+ if (dstWidth == srcImage->Width &&
+ dstHeight == srcImage->Height &&
+ dstDepth == srcImage->Depth) {
+ /* all done */
+ break;
}
- /* Create empty image */
- _mesa_TexImage2D(GL_TEXTURE_2D, level, srcImage->InternalFormat,
- newWidth, newHeight, border,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ /* Create empty dest image */
+ if (target == GL_TEXTURE_1D) {
+ _mesa_TexImage1D(target, dstLevel, srcImage->InternalFormat,
+ dstWidth, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ else if (target == GL_TEXTURE_3D) {
+ _mesa_TexImage3D(target, dstLevel, srcImage->InternalFormat,
+ dstWidth, dstHeight, dstDepth, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ else {
+ /* 2D or cube */
+ _mesa_TexImage2D(faceTarget, dstLevel, srcImage->InternalFormat,
+ dstWidth, dstHeight, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ /* If texturing from a cube, we need to make sure all src faces
+ * have been defined (even if we're not sampling from them.)
+ * Otherwise the texture object will be 'incomplete' and
+ * texturing from it will not be allowed.
+ */
+ GLuint face;
+ for (face = 0; face < 6; face++) {
+ if (!texObj->Image[face][srcLevel] ||
+ texObj->Image[face][srcLevel]->Width != srcWidth) {
+ _mesa_TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
+ srcLevel, srcImage->InternalFormat,
+ srcWidth, srcHeight, border,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ }
+ }
+ }
+ }
- /* vertex positions */
+ /* setup vertex positions */
{
verts[0].x = 0.0F;
verts[0].y = 0.0F;
- verts[1].x = (GLfloat) newWidth;
+ verts[1].x = (GLfloat) dstWidth;
verts[1].y = 0.0F;
- verts[2].x = (GLfloat) newWidth;
- verts[2].y = (GLfloat) newHeight;
+ verts[2].x = (GLfloat) dstWidth;
+ verts[2].y = (GLfloat) dstHeight;
verts[3].x = 0.0F;
- verts[3].y = (GLfloat) newHeight;
+ verts[3].y = (GLfloat) dstHeight;
/* upload new vertex data */
_mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
}
/* limit sampling to src level */
- _mesa_TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, srcLevel);
- _mesa_TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, srcLevel);
-
- /* Set to draw into the current level */
- _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target,
- texObj->Name,
- level);
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
+
+ /* Set to draw into the current dstLevel */
+ if (target == GL_TEXTURE_1D) {
+ _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texObj->Name,
+ dstLevel);
+ }
+ else if (target == GL_TEXTURE_3D) {
+ GLint zoffset = 0; /* XXX unfinished */
+ _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ target,
+ texObj->Name,
+ dstLevel, zoffset);
+ }
+ else {
+ /* 2D / cube */
+ _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ faceTarget,
+ texObj->Name,
+ dstLevel);
+ }
- /* Choose to render to the color attachment. */
_mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ /* sanity check */
status = _mesa_CheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
abort();
@@ -2101,12 +2386,19 @@ _mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
+ _mesa_lock_texture(ctx, texObj); /* relock */
+
_mesa_meta_end(ctx);
_mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterSave);
_mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
+ _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, wrapSSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, wrapTSave);
+ _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, wrapRSave);
- /* restore (XXX add to meta_begin/end()? */
_mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave);
}
@@ -2180,6 +2472,12 @@ copy_tex_image(GLcontext *ctx, GLuint dims, GLenum target, GLint level,
return;
}
+ if (texImage->TexFormat == &_mesa_null_texformat)
+ texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx,
+ internalFormat,
+ format,
+ type);
+
_mesa_unlock_texture(ctx, texObj); /* need to unlock first */
/*
diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
index 7f659528dc..6225b94189 100644
--- a/src/mesa/drivers/common/meta.h
+++ b/src/mesa/drivers/common/meta.h
@@ -60,6 +60,10 @@ _mesa_meta_Bitmap(GLcontext *ctx,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap);
+extern GLboolean
+_mesa_meta_check_generate_mipmap_fallback(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj);
+
extern void
_mesa_meta_GenerateMipmap(GLcontext *ctx, GLenum target,
struct gl_texture_object *texObj);