X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fcommon%2Fmeta_generate_mipmap.c;h=8ffd8da3bdeda693100bcacbfad3c64eb779e266;hb=89b1f5d6ac669343b1ee00f288e2ee71eb15dbe2;hp=6ca6f228976d47965096adea6e2efda1acf95f07;hpb=15b2f69b9c7d573bc978241da50549be4d3f2aca;p=mesa.git diff --git a/src/mesa/drivers/common/meta_generate_mipmap.c b/src/mesa/drivers/common/meta_generate_mipmap.c index 6ca6f228976..8ffd8da3bde 100644 --- a/src/mesa/drivers/common/meta_generate_mipmap.c +++ b/src/mesa/drivers/common/meta_generate_mipmap.c @@ -43,39 +43,8 @@ #include "main/varray.h" #include "main/viewport.h" #include "drivers/common/meta.h" +#include "program/prog_instruction.h" -/** - * Bind a particular texture level/layer to mipmap->FBO's GL_COLOR_ATTACHMENT0. - */ -static void -bind_fbo_image(struct gl_texture_object *texObj, GLenum target, - GLuint level, GLuint layer) -{ - switch (target) { - case GL_TEXTURE_1D: - _mesa_FramebufferTexture1D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - target, - texObj->Name, - level); - break; - case GL_TEXTURE_1D_ARRAY: - case GL_TEXTURE_2D_ARRAY: - case GL_TEXTURE_3D: - _mesa_FramebufferTextureLayer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - texObj->Name, - level, - layer); - break; - default: /* 2D / cube */ - _mesa_FramebufferTexture2D(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - target, - texObj->Name, - level); - } -} /** * Check if the call to _mesa_meta_GenerateMipmap() will require a @@ -94,9 +63,7 @@ fallback_required(struct gl_context *ctx, GLenum target, GLenum status; /* check for fallbacks */ - if (target == GL_TEXTURE_3D || - target == GL_TEXTURE_1D_ARRAY || - target == GL_TEXTURE_2D_ARRAY) { + if (target == GL_TEXTURE_3D) { _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH, "glGenerateMipmap() to %s target\n", _mesa_lookup_enum_by_nr(target)); @@ -137,7 +104,7 @@ fallback_required(struct gl_context *ctx, GLenum target, _mesa_GenFramebuffers(1, &mipmap->FBO); _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO); - bind_fbo_image(texObj, target, srcLevel, 0); + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, baseImage, 0); status = _mesa_CheckFramebufferStatus(GL_FRAMEBUFFER_EXT); @@ -165,6 +132,22 @@ _mesa_meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap) _mesa_meta_blit_shader_table_cleanup(&mipmap->shaders); } +static GLboolean +prepare_mipmap_level(struct gl_context *ctx, + struct gl_texture_object *texObj, GLuint level, + GLsizei width, GLsizei height, GLsizei depth, + GLenum intFormat, mesa_format format) +{ + if (texObj->Target == GL_TEXTURE_1D_ARRAY) { + /* Work around Mesa expecting the number of array slices in "height". */ + height = depth; + depth = 1; + } + + return _mesa_prepare_mipmap_level(ctx, texObj, level, width, height, depth, + 0, intFormat, format); +} + /** * Called via ctx->Driver.GenerateMipmap() * Note: We don't yet support 3D textures, 1D/2D array textures or texture @@ -180,14 +163,14 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, const GLuint maxLevel = texObj->MaxLevel; const GLint maxLevelSave = texObj->MaxLevel; const GLboolean genMipmapSave = texObj->GenerateMipmap; - const GLuint fboSave = ctx->DrawBuffer->Name; 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; - const GLint slice = 0; GLuint samplerSave; + GLint swizzle[4]; + GLboolean swizzleSaved = GL_FALSE; if (fallback_required(ctx, target, texObj)) { _mesa_generate_mipmap(ctx, target, texObj); @@ -202,14 +185,14 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, faceTarget = target; } - _mesa_meta_begin(ctx, MESA_META_ALL); + _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, 3, 0); + 2, 4, 0); _mesa_meta_setup_blit_shader(ctx, target, &mipmap->shaders); } else { _mesa_meta_setup_ff_tnl_for_blit(&mipmap->VAO, &mipmap->VBO, 3); @@ -251,18 +234,16 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_TexParameteri(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; + _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzleNoop); + } + /* Silence valgrind warnings about reading uninitialized stack. */ memset(verts, 0, sizeof(verts)); - /* Setup texture coordinates */ - _mesa_meta_setup_texture_coords(faceTarget, - slice, - 0, 0, 1, /* width, height never used here */ - verts[0].tex, - verts[1].tex, - verts[2].tex, - verts[3].tex); - /* setup vertex positions */ verts[0].x = -1.0F; verts[0].y = -1.0F; @@ -273,16 +254,14 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, verts[3].x = -1.0F; verts[3].y = 1.0F; - /* upload vertex data */ - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - verts, GL_DYNAMIC_DRAW_ARB); - /* 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; @@ -291,17 +270,22 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, /* src size */ srcWidth = srcImage->Width; - srcHeight = srcImage->Height; - srcDepth = srcImage->Depth; + 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 = minify(srcDepth, 1); + dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth; - if (dstWidth == srcImage->Width && - dstHeight == srcImage->Height && - dstDepth == srcImage->Depth) { + if (dstWidth == srcWidth && + dstHeight == srcHeight && + dstDepth == srcDepth) { /* all done */ break; } @@ -311,39 +295,57 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, /* Set MaxLevel large enough to hold the new level when we allocate it */ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel); - if (!_mesa_prepare_mipmap_level(ctx, texObj, dstLevel, - dstWidth, dstHeight, dstDepth, - srcImage->Border, - srcImage->InternalFormat, - srcImage->TexFormat)) { + 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(ctx, texObj, faceTarget, dstLevel); /* limit minification to src level */ _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); - bind_fbo_image(texObj, faceTarget, dstLevel, 0); - - _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - - /* sanity check */ - if (_mesa_CheckFramebufferStatus(GL_FRAMEBUFFER) != - GL_FRAMEBUFFER_COMPLETE) { - _mesa_problem(ctx, "Unexpected incomplete framebuffer in " - "_mesa_meta_GenerateMipmap()"); - break; - } - - assert(dstWidth == ctx->DrawBuffer->Width); - assert(dstHeight == ctx->DrawBuffer->Height); - /* setup viewport */ _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight); - - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + _mesa_DrawBuffer(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 */ + _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), + verts, GL_DYNAMIC_DRAW_ARB); + + _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstImage, layer); + + /* sanity check */ + if (_mesa_CheckFramebufferStatus(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); + } + + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + } } _mesa_lock_texture(ctx, texObj); /* relock */ @@ -355,6 +357,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); if (genMipmapSave) _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave); - - _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, fboSave); + if (swizzleSaved) + _mesa_TexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle); }