diff options
Diffstat (limited to 'mesalib/src/mesa')
69 files changed, 3183 insertions, 780 deletions
diff --git a/mesalib/src/mesa/Android.libmesa_dricore.mk b/mesalib/src/mesa/Android.libmesa_dricore.mk index 217f6498a..28d6feb35 100644 --- a/mesalib/src/mesa/Android.libmesa_dricore.mk +++ b/mesalib/src/mesa/Android.libmesa_dricore.mk @@ -50,6 +50,7 @@ endif # MESA_ENABLE_ASM ifeq ($(ARCH_X86_HAVE_SSE4_1),true) LOCAL_SRC_FILES += \ $(SRCDIR)main/streaming-load-memcpy.c +LOCAL_CFLAGS := -msse4.1 endif LOCAL_C_INCLUDES := \ diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am index 57c1e4a57..e71bccbbe 100644 --- a/mesalib/src/mesa/Makefile.am +++ b/mesalib/src/mesa/Makefile.am @@ -135,22 +135,20 @@ endif libmesa_la_SOURCES = \ $(MESA_FILES) \ $(PROGRAM_FILES) \ - $(MESA_ASM_FILES_FOR_ARCH) + $(MESA_ASM_FILES_FOR_ARCH) libmesa_la_LIBADD = \ - $(top_builddir)/src/glsl/libglsl.la \ - $(ARCH_LIBS) \ - $() + $(top_builddir)/src/glsl/libglsl.la \ + $(ARCH_LIBS) libmesagallium_la_SOURCES = \ $(MESA_GALLIUM_FILES) \ $(PROGRAM_FILES) \ - $(MESA_ASM_FILES_FOR_ARCH) + $(MESA_ASM_FILES_FOR_ARCH) libmesagallium_la_LIBADD = \ - $(top_builddir)/src/glsl/libglsl.la \ - $(ARCH_LIBS) \ - $() + $(top_builddir)/src/glsl/libglsl.la \ + $(ARCH_LIBS) libmesa_sse41_la_SOURCES = \ main/streaming-load-memcpy.c diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index 594565771..12336c074 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -97,6 +97,7 @@ MAIN_FILES = \ $(SRCDIR)main/stencil.c \ $(SRCDIR)main/syncobj.c \ $(SRCDIR)main/texcompress.c \ + $(SRCDIR)main/texcompress_bptc.c \ $(SRCDIR)main/texcompress_cpal.c \ $(SRCDIR)main/texcompress_rgtc.c \ $(SRCDIR)main/texcompress_s3tc.c \ diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index a1d06d412..90befd42d 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -1527,12 +1527,12 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) { const char *vs_source = "#extension GL_AMD_vertex_shader_layer : enable\n" + "#extension GL_ARB_draw_instanced : enable\n" "attribute vec4 position;\n" - "uniform int layer;\n" "void main()\n" "{\n" "#ifdef GL_AMD_vertex_shader_layer\n" - " gl_Layer = layer;\n" + " gl_Layer = gl_InstanceID;\n" "#endif\n" " gl_Position = position;\n" "}\n"; @@ -1568,7 +1568,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) _mesa_LinkProgram(clear->ShaderProg); clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg, "color"); - clear->LayerLocation = _mesa_GetUniformLocation(clear->ShaderProg, "layer"); has_integer_textures = _mesa_is_gles3(ctx) || (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130); @@ -1579,12 +1578,12 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) ralloc_asprintf(shader_source_mem_ctx, "#version 130\n" "#extension GL_AMD_vertex_shader_layer : enable\n" + "#extension GL_ARB_draw_instanced : enable\n" "in vec4 position;\n" - "uniform int layer;\n" "void main()\n" "{\n" "#ifdef GL_AMD_vertex_shader_layer\n" - " gl_Layer = layer;\n" + " gl_Layer = gl_InstanceID;\n" "#endif\n" " gl_Position = position;\n" "}\n"); @@ -1623,8 +1622,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) clear->IntegerColorLocation = _mesa_GetUniformLocation(clear->IntegerShaderProg, "color"); - clear->IntegerLayerLocation = - _mesa_GetUniformLocation(clear->IntegerShaderProg, "layer"); } } @@ -1653,8 +1650,8 @@ meta_glsl_clear_cleanup(struct clear_state *clear) * Since the bitfield has no associated order, the assignment of draw buffer * indices to color attachment indices is rather arbitrary. */ -static void -drawbuffers_from_bitfield(GLbitfield bits) +void +_mesa_meta_drawbuffers_from_bitfield(GLbitfield bits) { GLenum enums[MAX_DRAW_BUFFERS]; int i = 0; @@ -1767,7 +1764,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl) /* GL_COLOR_BUFFER_BIT */ if (buffers & BUFFER_BITS_COLOR) { /* Only draw to the buffers we were asked to clear. */ - drawbuffers_from_bitfield(buffers & BUFFER_BITS_COLOR); + _mesa_meta_drawbuffers_from_bitfield(buffers & BUFFER_BITS_COLOR); /* leave colormask state as-is */ @@ -1832,15 +1829,7 @@ meta_clear(struct gl_context *ctx, GLbitfield buffers, bool glsl) /* draw quad(s) */ if (fb->MaxNumLayers > 0) { - unsigned layer; - assert(glsl && clear->LayerLocation != -1); - for (layer = 0; layer < fb->MaxNumLayers; layer++) { - if (fb->_IntegerColor) - _mesa_Uniform1i(clear->IntegerLayerLocation, layer); - else - _mesa_Uniform1i(clear->LayerLocation, layer); - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); - } + _mesa_DrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, fb->MaxNumLayers); } else { _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } @@ -2784,7 +2773,6 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims, GLint x, GLint y, GLsizei width, GLsizei height) { - struct gl_texture_object *texObj = texImage->TexObject; GLuint fbo; bool success = false; GLbitfield mask; @@ -2793,8 +2781,6 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims, if (!ctx->Extensions.ARB_framebuffer_object) return false; - _mesa_unlock_texture(ctx, texObj); - _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS); _mesa_GenFramebuffers(1, &fbo); @@ -2845,7 +2831,6 @@ copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims, success = mask == 0x0; out: - _mesa_lock_texture(ctx, texObj); _mesa_DeleteFramebuffers(1, &fbo); _mesa_meta_end(ctx); return success; @@ -2863,7 +2848,6 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, GLint x, GLint y, GLsizei width, GLsizei height) { - struct gl_texture_object *texObj = texImage->TexObject; GLenum format, type; GLint bpp; void *buf; @@ -2908,8 +2892,6 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, return; } - _mesa_unlock_texture(ctx, texObj); /* need to unlock first */ - /* * Read image from framebuffer (disable pixel transfer ops) */ @@ -2938,19 +2920,25 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, _mesa_meta_end(ctx); - _mesa_lock_texture(ctx, texObj); /* re-lock */ - free(buf); } +static void +meta_decompress_fbo_cleanup(struct decompress_fbo_state *decompress_fbo) +{ + if (decompress_fbo->FBO != 0) { + _mesa_DeleteFramebuffers(1, &decompress_fbo->FBO); + _mesa_DeleteRenderbuffers(1, &decompress_fbo->RBO); + } + + memset(decompress_fbo, 0, sizeof(*decompress_fbo)); +} static void meta_decompress_cleanup(struct decompress_state *decompress) { - if (decompress->FBO != 0) { - _mesa_DeleteFramebuffers(1, &decompress->FBO); - _mesa_DeleteRenderbuffers(1, &decompress->RBO); - } + meta_decompress_fbo_cleanup(&decompress->byteFBO); + meta_decompress_fbo_cleanup(&decompress->floatFBO); if (decompress->VAO != 0) { _mesa_DeleteVertexArrays(1, &decompress->VAO); @@ -2972,7 +2960,7 @@ meta_decompress_cleanup(struct decompress_state *decompress) * \param dest destination buffer * \param destRowLength dest image rowLength (ala GL_PACK_ROW_LENGTH) */ -static void +static bool decompress_texture_image(struct gl_context *ctx, struct gl_texture_image *texImage, GLuint slice, @@ -2980,17 +2968,33 @@ decompress_texture_image(struct gl_context *ctx, GLvoid *dest) { struct decompress_state *decompress = &ctx->Meta->Decompress; + struct decompress_fbo_state *decompress_fbo; struct gl_texture_object *texObj = texImage->TexObject; const GLint width = texImage->Width; const GLint height = texImage->Height; const GLint depth = texImage->Height; const GLenum target = texObj->Target; + GLenum rbFormat; GLenum faceTarget; struct vertex verts[4]; GLuint samplerSave; + GLenum status; const bool use_glsl_version = ctx->Extensions.ARB_vertex_shader && ctx->Extensions.ARB_fragment_shader; + switch (_mesa_get_format_datatype(texImage->TexFormat)) { + case GL_FLOAT: + decompress_fbo = &decompress->floatFBO; + rbFormat = GL_RGBA32F; + break; + case GL_UNSIGNED_NORMALIZED: + decompress_fbo = &decompress->byteFBO; + rbFormat = GL_RGBA; + break; + default: + return false; + } + if (slice > 0) { assert(target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY || @@ -3001,11 +3005,11 @@ decompress_texture_image(struct gl_context *ctx, case GL_TEXTURE_1D: case GL_TEXTURE_1D_ARRAY: assert(!"No compressed 1D textures."); - return; + return false; case GL_TEXTURE_3D: assert(!"No compressed 3D textures."); - return; + return false; case GL_TEXTURE_CUBE_MAP_ARRAY: faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (slice % 6); @@ -3027,27 +3031,35 @@ decompress_texture_image(struct gl_context *ctx, ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; /* Create/bind FBO/renderbuffer */ - if (decompress->FBO == 0) { - _mesa_GenFramebuffers(1, &decompress->FBO); - _mesa_GenRenderbuffers(1, &decompress->RBO); - _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress->FBO); - _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress->RBO); + if (decompress_fbo->FBO == 0) { + _mesa_GenFramebuffers(1, &decompress_fbo->FBO); + _mesa_GenRenderbuffers(1, &decompress_fbo->RBO); + _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress_fbo->FBO); + _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress_fbo->RBO); _mesa_FramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, - decompress->RBO); + decompress_fbo->RBO); } else { - _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress->FBO); + _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, decompress_fbo->FBO); } /* alloc dest surface */ - if (width > decompress->Width || height > decompress->Height) { - _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress->RBO); - _mesa_RenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA, - width, height); - decompress->Width = width; - decompress->Height = height; + if (width > decompress_fbo->Width || height > decompress_fbo->Height) { + _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, decompress_fbo->RBO); + _mesa_RenderbufferStorage(GL_RENDERBUFFER_EXT, rbFormat, + width, height); + status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + /* If the framebuffer isn't complete then we'll leave + * decompress_fbo->Width as zero so that it will fail again next time + * too */ + _mesa_meta_end(ctx); + return false; + } + decompress_fbo->Width = width; + decompress_fbo->Height = height; } if (use_glsl_version) { @@ -3169,6 +3181,8 @@ decompress_texture_image(struct gl_context *ctx, _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); _mesa_meta_end(ctx); + + return true; } @@ -3182,17 +3196,10 @@ _mesa_meta_GetTexImage(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { - /* We can only use the decompress-with-blit method here if the texels are - * unsigned, normalized values. We could handle signed and unnormalized - * with floating point renderbuffers... - */ - if (_mesa_is_format_compressed(texImage->TexFormat) && - _mesa_get_format_datatype(texImage->TexFormat) - == GL_UNSIGNED_NORMALIZED) { - struct gl_texture_object *texObj = texImage->TexObject; + if (_mesa_is_format_compressed(texImage->TexFormat)) { GLuint slice; - /* Need to unlock the texture here to prevent deadlock... */ - _mesa_unlock_texture(ctx, texObj); + bool result; + for (slice = 0; slice < texImage->Depth; slice++) { void *dst; if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY @@ -3212,14 +3219,17 @@ _mesa_meta_GetTexImage(struct gl_context *ctx, else { dst = pixels; } - decompress_texture_image(ctx, texImage, slice, format, type, dst); + result = decompress_texture_image(ctx, texImage, slice, + format, type, dst); + if (!result) + break; } - /* ... and relock it */ - _mesa_lock_texture(ctx, texObj); - } - else { - _mesa_get_teximage(ctx, format, type, pixels, texImage); + + if (result) + return; } + + _mesa_get_teximage(ctx, format, type, pixels, texImage); } @@ -3515,15 +3525,11 @@ _mesa_meta_ClearTexSubImage(struct gl_context *ctx, { bool res; - _mesa_unlock_texture(ctx, texImage->TexObject); - res = cleartexsubimage_using_fbo(ctx, texImage, xoffset, yoffset, zoffset, width, height, depth, clearValue); - _mesa_lock_texture(ctx, texImage->TexObject); - if (res) return; diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index e2da2f427..56ba9bc65 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -343,13 +343,23 @@ struct gen_mipmap_state }; /** + * One of the FBO states for decompress_state. There will be one for each + * required renderbuffer format. + */ +struct decompress_fbo_state +{ + GLuint FBO, RBO; + GLint Width, Height; +}; + +/** * State for texture decompression */ struct decompress_state { GLuint VAO; - GLuint VBO, FBO, RBO, Sampler; - GLint Width, Height; + struct decompress_fbo_state byteFBO, floatFBO; + GLuint VBO, Sampler; struct blit_shader_table shaders; }; @@ -501,6 +511,9 @@ _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); /* meta-internal functions */ +void +_mesa_meta_drawbuffers_from_bitfield(GLbitfield bits); + GLuint _mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB *source); diff --git a/mesalib/src/mesa/drivers/dri/Android.mk b/mesalib/src/mesa/drivers/dri/Android.mk index e0cf51c58..935722c53 100644 --- a/mesalib/src/mesa/drivers/dri/Android.mk +++ b/mesalib/src/mesa/drivers/dri/Android.mk @@ -35,15 +35,15 @@ MESA_DRI_CFLAGS := \ -DHAVE_ANDROID_PLATFORM MESA_DRI_C_INCLUDES := \ + $(MESA_TOP)/src \ $(call intermediates-dir-for,STATIC_LIBRARIES,libmesa_dri_common) \ $(addprefix $(MESA_TOP)/, $(mesa_dri_common_INCLUDES)) \ - $(DRM_TOP) \ - $(DRM_TOP)/include/drm \ + $(TARGET_OUT_HEADERS)/libdrm \ external/expat/lib MESA_DRI_WHOLE_STATIC_LIBRARIES := \ libmesa_glsl \ - libmegadriver_stub \ + libmesa_megadriver_stub \ libmesa_dri_common \ libmesa_dricore diff --git a/mesalib/src/mesa/drivers/dri/common/Android.mk b/mesalib/src/mesa/drivers/dri/common/Android.mk index a172a0bc6..b95feb679 100644 --- a/mesalib/src/mesa/drivers/dri/common/Android.mk +++ b/mesalib/src/mesa/drivers/dri/common/Android.mk @@ -88,13 +88,13 @@ include $(MESA_COMMON_MK) include $(BUILD_STATIC_LIBRARY) # -# Build libmegadriver_stub +# Build libmesa_megadriver_stub # include $(CLEAR_VARS) include $(LOCAL_PATH)/Makefile.sources -LOCAL_MODULE := libmegadriver_stub +LOCAL_MODULE := libmesa_megadriver_stub LOCAL_MODULE_CLASS := STATIC_LIBRARIES LOCAL_C_INCLUDES := \ $(MESA_DRI_C_INCLUDES) diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c index eee77ec69..e0b3db8cf 100644 --- a/mesalib/src/mesa/drivers/dri/common/utils.c +++ b/mesalib/src/mesa/drivers/dri/common/utils.c @@ -519,6 +519,10 @@ driQueryRendererIntegerCommon(__DRIscreen *psp, int param, unsigned int *value) value[2] = v[2]; return 0; } + case __DRI2_RENDERER_PREFERRED_PROFILE: + value[0] = (psp->max_gl_core_version != 0) + ? (1U << __DRI_API_OPENGL_CORE) : (1U << __DRI_API_OPENGL); + return 0; case __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION: value[0] = psp->max_gl_core_version / 10; value[1] = psp->max_gl_core_version % 10; diff --git a/mesalib/src/mesa/drivers/dri/swrast/swrast.c b/mesalib/src/mesa/drivers/dri/swrast/swrast.c index b9a5d71ef..738bee250 100644 --- a/mesalib/src/mesa/drivers/dri/swrast/swrast.c +++ b/mesalib/src/mesa/drivers/dri/swrast/swrast.c @@ -66,6 +66,9 @@ PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void); +const char const *swrast_vendor_string = "Mesa Project"; +const char const *swrast_renderer_string = "Software Rasterizer"; + /** * Screen and config-related functions */ @@ -122,8 +125,74 @@ static const __DRItexBufferExtension swrastTexBufferExtension = { .releaseTexBuffer = NULL, }; + +static int +swrast_query_renderer_integer(__DRIscreen *psp, int param, + unsigned int *value) +{ + switch (param) { + case __DRI2_RENDERER_VENDOR_ID: + case __DRI2_RENDERER_DEVICE_ID: + /* Return 0xffffffff for both vendor and device id */ + value[0] = 0xffffffff; + return 0; + case __DRI2_RENDERER_ACCELERATED: + value[0] = 0; + return 0; + case __DRI2_RENDERER_VIDEO_MEMORY: { + /* XXX: Do we want to return the full amount of system memory ? */ + const long system_memory_pages = sysconf(_SC_PHYS_PAGES); + const long system_page_size = sysconf(_SC_PAGE_SIZE); + + if (system_memory_pages <= 0 || system_page_size <= 0) + return -1; + + const uint64_t system_memory_bytes = (uint64_t) system_memory_pages + * (uint64_t) system_page_size; + + const unsigned system_memory_megabytes = + (unsigned) (system_memory_bytes / (1024 * 1024)); + + value[0] = system_memory_megabytes; + return 0; + } + case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE: + /** + * XXX: Perhaps we should return 1 ? + * See issue #7 from the spec, currently UNRESOLVED. + */ + value[0] = 0; + return 0; + default: + return driQueryRendererIntegerCommon(psp, param, value); + } +} + +static int +swrast_query_renderer_string(__DRIscreen *psp, int param, const char **value) +{ + switch (param) { + case __DRI2_RENDERER_VENDOR_ID: + value[0] = swrast_vendor_string; + return 0; + case __DRI2_RENDERER_DEVICE_ID: + value[0] = swrast_renderer_string; + return 0; + default: + return -1; + } +} + +static const __DRI2rendererQueryExtension swrast_query_renderer_extension = { + .base = { __DRI2_RENDERER_QUERY, 1 }, + + .queryInteger = swrast_query_renderer_integer, + .queryString = swrast_query_renderer_string +}; + static const __DRIextension *dri_screen_extensions[] = { &swrastTexBufferExtension.base, + &swrast_query_renderer_extension.base, NULL }; @@ -604,9 +673,9 @@ get_string(struct gl_context *ctx, GLenum pname) (void) ctx; switch (pname) { case GL_VENDOR: - return (const GLubyte *) "Mesa Project"; + return (const GLubyte *) swrast_vendor_string; case GL_RENDERER: - return (const GLubyte *) "Software Rasterizer"; + return (const GLubyte *) swrast_renderer_string; default: return NULL; } diff --git a/mesalib/src/mesa/drivers/haiku/swrast/SConscript b/mesalib/src/mesa/drivers/haiku/swrast/SConscript index aef730098..2c25f727d 100644 --- a/mesalib/src/mesa/drivers/haiku/swrast/SConscript +++ b/mesalib/src/mesa/drivers/haiku/swrast/SConscript @@ -3,6 +3,7 @@ Import('*') env = env.Clone() env.Append(CPPPATH = [ + '#/src', '#/src/mapi', '#/src/mesa', '#/src/mesa/main', diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index 140cf6e82..8a0852c42 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -498,7 +498,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, * (ex: glDrawBuffer(GL_FRONT_AND_BACK)). * Otherwise, destMask[x] can only have one bit set. */ - if (_mesa_bitcount(destMask[0]) > 1) { + if (n > 0 && _mesa_bitcount(destMask[0]) > 1) { GLuint count = 0, destMask0 = destMask[0]; while (destMask0) { GLint bufIndex = ffs(destMask0) - 1; diff --git a/mesalib/src/mesa/main/condrender.c b/mesalib/src/mesa/main/condrender.c index 0ad1e5c2a..75f9d74bc 100644 --- a/mesalib/src/mesa/main/condrender.c +++ b/mesalib/src/mesa/main/condrender.c @@ -77,8 +77,14 @@ _mesa_BeginConditionalRender(GLuint queryId, GLenum mode) case GL_QUERY_NO_WAIT: case GL_QUERY_BY_REGION_WAIT: case GL_QUERY_BY_REGION_NO_WAIT: - /* OK */ - break; + break; /* OK */ + case GL_QUERY_WAIT_INVERTED: + case GL_QUERY_NO_WAIT_INVERTED: + case GL_QUERY_BY_REGION_WAIT_INVERTED: + case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: + if (ctx->Extensions.ARB_conditional_render_inverted) + break; /* OK */ + /* fallthrough - invalid */ default: _mesa_error(ctx, GL_INVALID_ENUM, "glBeginConditionalRender(mode=%s)", _mesa_lookup_enum_by_nr(mode)); @@ -156,12 +162,25 @@ _mesa_check_conditional_render(struct gl_context *ctx) ctx->Driver.WaitQuery(ctx, q); } return q->Result > 0; + case GL_QUERY_BY_REGION_WAIT_INVERTED: + /* fall-through */ + case GL_QUERY_WAIT_INVERTED: + if (!q->Ready) { + ctx->Driver.WaitQuery(ctx, q); + } + return q->Result == 0; case GL_QUERY_BY_REGION_NO_WAIT: /* fall-through */ case GL_QUERY_NO_WAIT: if (!q->Ready) ctx->Driver.CheckQuery(ctx, q); return q->Ready ? (q->Result > 0) : GL_TRUE; + case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: + /* fall-through */ + case GL_QUERY_NO_WAIT_INVERTED: + if (!q->Ready) + ctx->Driver.CheckQuery(ctx, q); + return q->Ready ? (q->Result == 0) : GL_TRUE; default: _mesa_problem(ctx, "Bad cond render mode %s in " " _mesa_check_conditional_render()", diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 50aae8bf6..232084267 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -464,7 +464,7 @@ _mesa_init_current(struct gl_context *ctx) * Important: drivers should override these with actual limits. */ static void -init_program_limits(struct gl_context *ctx, gl_shader_stage stage, +init_program_limits(struct gl_constants *consts, gl_shader_stage stage, struct gl_program_constants *prog) { prog->MaxInstructions = MAX_PROGRAM_INSTRUCTIONS; @@ -546,7 +546,7 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage, prog->MaxUniformBlocks = 12; prog->MaxCombinedUniformComponents = (prog->MaxUniformComponents + - ctx->Const.MaxUniformBlockSize / 4 * + consts->MaxUniformBlockSize / 4 * prog->MaxUniformBlocks); prog->MaxAtomicBuffers = 0; @@ -559,161 +559,161 @@ init_program_limits(struct gl_context *ctx, gl_shader_stage stage, * Use defaults from config.h. The device drivers will often override * some of these values (such as number of texture units). */ -static void -_mesa_init_constants(struct gl_context *ctx) +void +_mesa_init_constants(struct gl_constants *consts, gl_api api) { int i; - assert(ctx); + assert(consts); /* Constants, may be overriden (usually only reduced) by device drivers */ - ctx->Const.MaxTextureMbytes = MAX_TEXTURE_MBYTES; - ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS; - ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS; - ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS; - ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE; - ctx->Const.MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS; - ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS; - ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits, - ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits); - ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY; - ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS; - ctx->Const.MaxTextureBufferSize = 65536; - ctx->Const.TextureBufferOffsetAlignment = 1; - ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE; - ctx->Const.SubPixelBits = SUB_PIXEL_BITS; - ctx->Const.MinPointSize = MIN_POINT_SIZE; - ctx->Const.MaxPointSize = MAX_POINT_SIZE; - ctx->Const.MinPointSizeAA = MIN_POINT_SIZE; - ctx->Const.MaxPointSizeAA = MAX_POINT_SIZE; - ctx->Const.PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY; - ctx->Const.MinLineWidth = MIN_LINE_WIDTH; - ctx->Const.MaxLineWidth = MAX_LINE_WIDTH; - ctx->Const.MinLineWidthAA = MIN_LINE_WIDTH; - ctx->Const.MaxLineWidthAA = MAX_LINE_WIDTH; - ctx->Const.LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY; - ctx->Const.MaxClipPlanes = 6; - ctx->Const.MaxLights = MAX_LIGHTS; - ctx->Const.MaxShininess = 128.0; - ctx->Const.MaxSpotExponent = 128.0; - ctx->Const.MaxViewportWidth = MAX_VIEWPORT_WIDTH; - ctx->Const.MaxViewportHeight = MAX_VIEWPORT_HEIGHT; - ctx->Const.MinMapBufferAlignment = 64; + consts->MaxTextureMbytes = MAX_TEXTURE_MBYTES; + consts->MaxTextureLevels = MAX_TEXTURE_LEVELS; + consts->Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS; + consts->MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS; + consts->MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE; + consts->MaxArrayTextureLayers = MAX_ARRAY_TEXTURE_LAYERS; + consts->MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS; + consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + consts->MaxTextureUnits = MIN2(consts->MaxTextureCoordUnits, + consts->Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits); + consts->MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY; + consts->MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS; + consts->MaxTextureBufferSize = 65536; + consts->TextureBufferOffsetAlignment = 1; + consts->MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE; + consts->SubPixelBits = SUB_PIXEL_BITS; + consts->MinPointSize = MIN_POINT_SIZE; + consts->MaxPointSize = MAX_POINT_SIZE; + consts->MinPointSizeAA = MIN_POINT_SIZE; + consts->MaxPointSizeAA = MAX_POINT_SIZE; + consts->PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY; + consts->MinLineWidth = MIN_LINE_WIDTH; + consts->MaxLineWidth = MAX_LINE_WIDTH; + consts->MinLineWidthAA = MIN_LINE_WIDTH; + consts->MaxLineWidthAA = MAX_LINE_WIDTH; + consts->LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY; + consts->MaxClipPlanes = 6; + consts->MaxLights = MAX_LIGHTS; + consts->MaxShininess = 128.0; + consts->MaxSpotExponent = 128.0; + consts->MaxViewportWidth = MAX_VIEWPORT_WIDTH; + consts->MaxViewportHeight = MAX_VIEWPORT_HEIGHT; + consts->MinMapBufferAlignment = 64; /* Driver must override these values if ARB_viewport_array is supported. */ - ctx->Const.MaxViewports = 1; - ctx->Const.ViewportSubpixelBits = 0; - ctx->Const.ViewportBounds.Min = 0; - ctx->Const.ViewportBounds.Max = 0; + consts->MaxViewports = 1; + consts->ViewportSubpixelBits = 0; + consts->ViewportBounds.Min = 0; + consts->ViewportBounds.Max = 0; /** GL_ARB_uniform_buffer_object */ - ctx->Const.MaxCombinedUniformBlocks = 36; - ctx->Const.MaxUniformBufferBindings = 36; - ctx->Const.MaxUniformBlockSize = 16384; - ctx->Const.UniformBufferOffsetAlignment = 1; + consts->MaxCombinedUniformBlocks = 36; + consts->MaxUniformBufferBindings = 36; + consts->MaxUniformBlockSize = 16384; + consts->UniformBufferOffsetAlignment = 1; /* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */ - ctx->Const.MaxUserAssignableUniformLocations = + consts->MaxUserAssignableUniformLocations = 4 * MESA_SHADER_STAGES * MAX_UNIFORMS; for (i = 0; i < MESA_SHADER_STAGES; i++) - init_program_limits(ctx, i, &ctx->Const.Program[i]); + init_program_limits(consts, i, &consts->Program[i]); - ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES; - ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; + consts->MaxProgramMatrices = MAX_PROGRAM_MATRICES; + consts->MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; /* CheckArrayBounds is overriden by drivers/x11 for X server */ - ctx->Const.CheckArrayBounds = GL_FALSE; + consts->CheckArrayBounds = GL_FALSE; /* GL_ARB_draw_buffers */ - ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS; + consts->MaxDrawBuffers = MAX_DRAW_BUFFERS; - ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS; - ctx->Const.MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE; + consts->MaxColorAttachments = MAX_COLOR_ATTACHMENTS; + consts->MaxRenderbufferSize = MAX_RENDERBUFFER_SIZE; - ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxVarying = 16; /* old limit not to break tnl and swrast */ - ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - ctx->Const.MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES; - ctx->Const.MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS; + consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + consts->MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS; + consts->MaxVarying = 16; /* old limit not to break tnl and swrast */ + consts->Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + consts->MaxGeometryOutputVertices = MAX_GEOMETRY_OUTPUT_VERTICES; + consts->MaxGeometryTotalOutputComponents = MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS; /* Shading language version */ - if (_mesa_is_desktop_gl(ctx)) { - ctx->Const.GLSLVersion = 120; - _mesa_override_glsl_version(ctx); + if (api == API_OPENGL_COMPAT || api == API_OPENGL_CORE) { + consts->GLSLVersion = 120; + _mesa_override_glsl_version(consts); } - else if (ctx->API == API_OPENGLES2) { - ctx->Const.GLSLVersion = 100; + else if (api == API_OPENGLES2) { + consts->GLSLVersion = 100; } - else if (ctx->API == API_OPENGLES) { - ctx->Const.GLSLVersion = 0; /* GLSL not supported */ + else if (api == API_OPENGLES) { + consts->GLSLVersion = 0; /* GLSL not supported */ } /* GL_ARB_framebuffer_object */ - ctx->Const.MaxSamples = 0; + consts->MaxSamples = 0; /* GL_ARB_sync */ - ctx->Const.MaxServerWaitTimeout = 0x1fff7fffffffULL; + consts->MaxServerWaitTimeout = 0x1fff7fffffffULL; /* GL_EXT_provoking_vertex */ - ctx->Const.QuadsFollowProvokingVertexConvention = GL_TRUE; + consts->QuadsFollowProvokingVertexConvention = GL_TRUE; /* GL_EXT_transform_feedback */ - ctx->Const.MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS; - ctx->Const.MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS; - ctx->Const.MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS; - ctx->Const.MaxVertexStreams = 1; + consts->MaxTransformFeedbackBuffers = MAX_FEEDBACK_BUFFERS; + consts->MaxTransformFeedbackSeparateComponents = 4 * MAX_FEEDBACK_ATTRIBS; + consts->MaxTransformFeedbackInterleavedComponents = 4 * MAX_FEEDBACK_ATTRIBS; + consts->MaxVertexStreams = 1; /* GL 3.2 */ - ctx->Const.ProfileMask = ctx->API == API_OPENGL_CORE + consts->ProfileMask = api == API_OPENGL_CORE ? GL_CONTEXT_CORE_PROFILE_BIT : GL_CONTEXT_COMPATIBILITY_PROFILE_BIT; /** GL_EXT_gpu_shader4 */ - ctx->Const.MinProgramTexelOffset = -8; - ctx->Const.MaxProgramTexelOffset = 7; + consts->MinProgramTexelOffset = -8; + consts->MaxProgramTexelOffset = 7; /* GL_ARB_texture_gather */ - ctx->Const.MinProgramTextureGatherOffset = -8; - ctx->Const.MaxProgramTextureGatherOffset = 7; + consts->MinProgramTextureGatherOffset = -8; + consts->MaxProgramTextureGatherOffset = 7; /* GL_ARB_robustness */ - ctx->Const.ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB; + consts->ResetStrategy = GL_NO_RESET_NOTIFICATION_ARB; /* PrimitiveRestart */ - ctx->Const.PrimitiveRestartInSoftware = GL_FALSE; + consts->PrimitiveRestartInSoftware = GL_FALSE; /* ES 3.0 or ARB_ES3_compatibility */ - ctx->Const.MaxElementIndex = 0xffffffffu; + consts->MaxElementIndex = 0xffffffffu; /* GL_ARB_texture_multisample */ - ctx->Const.MaxColorTextureSamples = 1; - ctx->Const.MaxDepthTextureSamples = 1; - ctx->Const.MaxIntegerSamples = 1; + consts->MaxColorTextureSamples = 1; + consts->MaxDepthTextureSamples = 1; + consts->MaxIntegerSamples = 1; /* GL_ARB_shader_atomic_counters */ - ctx->Const.MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS; - ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; - ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; - ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS; + consts->MaxAtomicBufferBindings = MAX_COMBINED_ATOMIC_BUFFERS; + consts->MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; + consts->MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; + consts->MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS; /* GL_ARB_vertex_attrib_binding */ - ctx->Const.MaxVertexAttribRelativeOffset = 2047; - ctx->Const.MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS; + consts->MaxVertexAttribRelativeOffset = 2047; + consts->MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS; /* GL_ARB_compute_shader */ - ctx->Const.MaxComputeWorkGroupCount[0] = 65535; - ctx->Const.MaxComputeWorkGroupCount[1] = 65535; - ctx->Const.MaxComputeWorkGroupCount[2] = 65535; - ctx->Const.MaxComputeWorkGroupSize[0] = 1024; - ctx->Const.MaxComputeWorkGroupSize[1] = 1024; - ctx->Const.MaxComputeWorkGroupSize[2] = 64; - ctx->Const.MaxComputeWorkGroupInvocations = 1024; + consts->MaxComputeWorkGroupCount[0] = 65535; + consts->MaxComputeWorkGroupCount[1] = 65535; + consts->MaxComputeWorkGroupCount[2] = 65535; + consts->MaxComputeWorkGroupSize[0] = 1024; + consts->MaxComputeWorkGroupSize[1] = 1024; + consts->MaxComputeWorkGroupSize[2] = 64; + consts->MaxComputeWorkGroupInvocations = 1024; /** GL_ARB_gpu_shader5 */ - ctx->Const.MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET; - ctx->Const.MaxFragmentInterpolationOffset = MAX_FRAGMENT_INTERPOLATION_OFFSET; + consts->MinFragmentInterpolationOffset = MIN_FRAGMENT_INTERPOLATION_OFFSET; + consts->MaxFragmentInterpolationOffset = MAX_FRAGMENT_INTERPOLATION_OFFSET; } @@ -790,10 +790,10 @@ init_attrib_groups(struct gl_context *ctx) assert(ctx); /* Constants */ - _mesa_init_constants( ctx ); + _mesa_init_constants(&ctx->Const, ctx->API); /* Extensions */ - _mesa_init_extensions( ctx ); + _mesa_init_extensions(&ctx->Extensions); /* Attribute Groups */ _mesa_init_accum( ctx ); diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h index 792ab4cd5..d902ea76e 100644 --- a/mesalib/src/mesa/main/context.h +++ b/mesalib/src/mesa/main/context.h @@ -144,6 +144,9 @@ _mesa_get_current_context(void); /*@}*/ extern void +_mesa_init_constants(struct gl_constants *consts, gl_api api); + +extern void _mesa_init_get_hash(struct gl_context *ctx); extern void diff --git a/mesalib/src/mesa/main/copyimage.c b/mesalib/src/mesa/main/copyimage.c index dcbc83de6..df7d7c272 100644 --- a/mesalib/src/mesa/main/copyimage.c +++ b/mesalib/src/mesa/main/copyimage.c @@ -277,6 +277,12 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcWidth); + if (!ctx->Extensions.ARB_copy_image) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyImageSubData(extension not available)"); + return; + } + if (!prepare_target(ctx, srcName, &srcTarget, srcLevel, &srcTexObj, &srcTexImage, &tmpTexNames[0], "src")) goto cleanup; @@ -328,7 +334,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, srcTexImage->InternalFormat, dstTexImage->InternalFormat)) { } else { - return; /* Error loged by _mesa_texture_view_compatible_format */ + return; /* Error logged by _mesa_texture_view_compatible_format */ } for (i = 0; i < srcDepth; ++i) { diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index d60838a1c..553c01e34 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -94,6 +94,7 @@ static const struct extension extension_table[] = { { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, { "GL_ARB_compressed_texture_pixel_storage", o(dummy_true), GL, 2011 }, { "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 }, + { "GL_ARB_conditional_render_inverted", o(ARB_conditional_render_inverted), GL, 2014 }, { "GL_ARB_copy_buffer", o(dummy_true), GL, 2008 }, { "GL_ARB_copy_image", o(ARB_copy_image), GL, 2012 }, { "GL_ARB_conservative_depth", o(ARB_conservative_depth), GL, 2011 }, @@ -101,6 +102,7 @@ static const struct extension extension_table[] = { { "GL_ARB_depth_buffer_float", o(ARB_depth_buffer_float), GL, 2008 }, { "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL, 2003 }, { "GL_ARB_depth_texture", o(ARB_depth_texture), GLL, 2001 }, + { "GL_ARB_derivative_control", o(ARB_derivative_control), GL, 2014 }, { "GL_ARB_draw_buffers", o(dummy_true), GL, 2002 }, { "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL, 2009 }, { "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL, 2009 }, @@ -116,7 +118,7 @@ static const struct extension extension_table[] = { { "GL_ARB_framebuffer_object", o(ARB_framebuffer_object), GL, 2005 }, { "GL_ARB_framebuffer_sRGB", o(EXT_framebuffer_sRGB), GL, 1998 }, { "GL_ARB_get_program_binary", o(dummy_true), GL, 2010 }, - { "GL_ARB_gpu_shader5", o(ARB_gpu_shader5), GL, 2010 }, + { "GL_ARB_gpu_shader5", o(ARB_gpu_shader5), GLC, 2010 }, { "GL_ARB_half_float_pixel", o(dummy_true), GL, 2003 }, { "GL_ARB_half_float_vertex", o(ARB_half_float_vertex), GL, 2008 }, { "GL_ARB_instanced_arrays", o(ARB_instanced_arrays), GL, 2008 }, @@ -152,11 +154,13 @@ static const struct extension extension_table[] = { { "GL_ARB_shadow", o(ARB_shadow), GLL, 2001 }, { "GL_ARB_stencil_texturing", o(ARB_stencil_texturing), GL, 2012 }, { "GL_ARB_sync", o(ARB_sync), GL, 2003 }, + { "GL_ARB_texture_barrier", o(NV_texture_barrier), GL, 2014 }, { "GL_ARB_texture_border_clamp", o(ARB_texture_border_clamp), GLL, 2000 }, { "GL_ARB_texture_buffer_object", o(ARB_texture_buffer_object), GLC, 2008 }, { "GL_ARB_texture_buffer_object_rgb32", o(ARB_texture_buffer_object_rgb32), GLC, 2009 }, { "GL_ARB_texture_buffer_range", o(ARB_texture_buffer_range), GLC, 2012 }, { "GL_ARB_texture_compression", o(dummy_true), GLL, 2000 }, + { "GL_ARB_texture_compression_bptc", o(ARB_texture_compression_bptc), GL, 2010 }, { "GL_ARB_texture_compression_rgtc", o(ARB_texture_compression_rgtc), GL, 2004 }, { "GL_ARB_texture_cube_map", o(ARB_texture_cube_map), GLL, 1999 }, { "GL_ARB_texture_cube_map_array", o(ARB_texture_cube_map_array), GL, 2009 }, @@ -449,6 +453,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ARB_point_sprite = GL_TRUE; ctx->Extensions.ARB_shadow = GL_TRUE; ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; + ctx->Extensions.ARB_texture_compression_bptc = GL_TRUE; ctx->Extensions.ARB_texture_cube_map = GL_TRUE; ctx->Extensions.ARB_texture_env_combine = GL_TRUE; ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; @@ -667,9 +672,9 @@ _mesa_one_time_init_extension_overrides(void) * Note: Sets gl_extensions.dummy_true to true. */ void -_mesa_init_extensions( struct gl_context *ctx ) +_mesa_init_extensions(struct gl_extensions *extensions) { - GLboolean *base = (GLboolean *) &ctx->Extensions; + GLboolean *base = (GLboolean *) extensions; GLboolean *sentinel = base + o(extension_sentinel); GLboolean *i; @@ -678,8 +683,8 @@ _mesa_init_extensions( struct gl_context *ctx ) *i = GL_FALSE; /* Then, selectively turn default extensions on. */ - ctx->Extensions.dummy_true = GL_TRUE; - ctx->Extensions.EXT_texture3D = GL_TRUE; + extensions->dummy_true = GL_TRUE; + extensions->EXT_texture3D = GL_TRUE; } diff --git a/mesalib/src/mesa/main/extensions.h b/mesalib/src/mesa/main/extensions.h index 3a404d2e0..595512a5d 100644 --- a/mesalib/src/mesa/main/extensions.h +++ b/mesalib/src/mesa/main/extensions.h @@ -45,7 +45,7 @@ extern void _mesa_enable_sw_extensions(struct gl_context *ctx); extern void _mesa_one_time_init_extension_overrides(void); -extern void _mesa_init_extensions(struct gl_context *ctx); +extern void _mesa_init_extensions(struct gl_extensions *extentions); extern GLubyte *_mesa_make_extension_string(struct gl_context *ctx); diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 8758b5e9d..9bb706cc5 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -1252,7 +1252,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key) validate_ir_tree(p.shader->ir); const struct gl_shader_compiler_options *options = - &ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; + &ctx->Const.ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; while (do_common_optimization(p.shader->ir, false, false, options, ctx->Const.NativeIntegers)) diff --git a/mesalib/src/mesa/main/ffvertex_prog.c b/mesalib/src/mesa/main/ffvertex_prog.c index 728cf968b..d5afc3d81 100644 --- a/mesalib/src/mesa/main/ffvertex_prog.c +++ b/mesalib/src/mesa/main/ffvertex_prog.c @@ -1676,7 +1676,7 @@ _mesa_get_fixed_func_vertex_program(struct gl_context *ctx) return NULL; create_new_program( &key, prog, - ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS, + ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS, ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps ); #if 0 diff --git a/mesalib/src/mesa/main/format_info.py b/mesalib/src/mesa/main/format_info.py index 448bd0055..7424fe0cd 100644 --- a/mesalib/src/mesa/main/format_info.py +++ b/mesalib/src/mesa/main/format_info.py @@ -62,7 +62,9 @@ def get_gl_base_format(fmat): def get_gl_data_type(fmat): if fmat.is_compressed(): - if 'SIGNED' in fmat.name or 'SNORM' in fmat.name: + if 'FLOAT' in fmat.name: + return 'GL_FLOAT' + elif 'SIGNED' in fmat.name or 'SNORM' in fmat.name: return 'GL_SIGNED_NORMALIZED' else: return 'GL_UNSIGNED_NORMALIZED' @@ -125,6 +127,9 @@ def get_channel_bits(fmat, chan_name): bits = 11 if fmat.name.endswith('11_EAC') else 8 return bits if fmat.has_channel(chan_name) else 0 + elif fmat.layout == 'bptc': + bits = 16 if fmat.name.endswith('_FLOAT') else 8 + return bits if fmat.has_channel(chan_name) else 0 else: assert False else: diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index f03425e41..db22a45c4 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -369,6 +369,7 @@ _mesa_get_format_color_encoding(mesa_format format) case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: case MESA_FORMAT_B8G8R8X8_SRGB: + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: return GL_SRGB; default: return GL_LINEAR; @@ -377,6 +378,31 @@ _mesa_get_format_color_encoding(mesa_format format) /** + * Return TRUE if format is an ETC2 compressed format specified + * by GL_ARB_ES3_compatibility. + */ +bool +_mesa_is_format_etc2(mesa_format format) +{ + switch (format) { + case MESA_FORMAT_ETC2_RGB8: + case MESA_FORMAT_ETC2_SRGB8: + case MESA_FORMAT_ETC2_RGBA8_EAC: + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + case MESA_FORMAT_ETC2_R11_EAC: + case MESA_FORMAT_ETC2_RG11_EAC: + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** * For an sRGB format, return the corresponding linear color space format. * For non-sRGB formats, return the format as-is. */ @@ -426,6 +452,9 @@ _mesa_get_srgb_format_linear(mesa_format format) case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: format = MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1; break; + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + format = MESA_FORMAT_BPTC_RGBA_UNORM; + break; case MESA_FORMAT_B8G8R8X8_SRGB: format = MESA_FORMAT_B8G8R8X8_UNORM; break; @@ -491,6 +520,12 @@ _mesa_get_uncompressed_format(mesa_format format) case MESA_FORMAT_ETC2_RG11_EAC: case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: return MESA_FORMAT_R16G16_UNORM; + case MESA_FORMAT_BPTC_RGBA_UNORM: + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + return MESA_FORMAT_A8B8G8R8_UNORM; + case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: + case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: + return MESA_FORMAT_RGB_FLOAT32; default: #ifdef DEBUG assert(!_mesa_is_format_compressed(format)); @@ -968,6 +1003,10 @@ _mesa_format_to_type_and_comps(mesa_format format, case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + case MESA_FORMAT_BPTC_RGBA_UNORM: + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: + case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: /* XXX generate error instead? */ *datatype = GL_UNSIGNED_BYTE; *comps = 0; @@ -1524,6 +1563,12 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format, case MESA_FORMAT_RGBA_DXT5: return GL_FALSE; + case MESA_FORMAT_BPTC_RGBA_UNORM: + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: + case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: + return GL_FALSE; + case MESA_FORMAT_RGBA_FLOAT32: return format == GL_RGBA && type == GL_FLOAT && !swapBytes; case MESA_FORMAT_RGBA_FLOAT16: diff --git a/mesalib/src/mesa/main/formats.csv b/mesalib/src/mesa/main/formats.csv index eade6facd..4d542b7c6 100644 --- a/mesalib/src/mesa/main/formats.csv +++ b/mesalib/src/mesa/main/formats.csv @@ -280,3 +280,9 @@ MESA_FORMAT_ETC2_SIGNED_R11_EAC , etc2 , 4, 4, x64 , , , MESA_FORMAT_ETC2_SIGNED_RG11_EAC , etc2 , 4, 4, x128, , , , xy01, rgb MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1 , etc2 , 4, 4, x64 , , , , xyzw, rgb MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, etc2 , 4, 4, x64 , , , , xyzw, srgb + +# BPTC compressed formats +MESA_FORMAT_BPTC_RGBA_UNORM , bptc , 4, 4, x128, , , , xyzw, rgb +MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM , bptc , 4, 4, x128, , , , xyzw, srgb +MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT , bptc , 4, 4, x128, , , , xyz1, rgb +MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT , bptc , 4, 4, x128, , , , xyz1, rgb diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 457c8abf8..d6253bf86 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -427,6 +427,12 @@ typedef enum MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, + /* BPTC compressed formats */ + MESA_FORMAT_BPTC_RGBA_UNORM, + MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM, + MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT, + MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT, + MESA_FORMAT_COUNT } mesa_format; @@ -476,6 +482,9 @@ _mesa_is_format_signed(mesa_format format); extern GLboolean _mesa_is_format_integer(mesa_format format); +extern bool +_mesa_is_format_etc2(mesa_format format); + extern GLenum _mesa_get_format_color_encoding(mesa_format format); diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 0fb25ba0f..00478f989 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -787,6 +787,10 @@ _mesa_is_color_format(GLenum format) case GL_COMPRESSED_SIGNED_RG11_EAC: case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: /* generic integer formats */ case GL_RED_INTEGER_EXT: case GL_GREEN_INTEGER_EXT: @@ -1040,6 +1044,12 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format) case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return _mesa_is_gles3(ctx) || ctx->Extensions.ARB_ES3_compatibility; + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + return _mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_texture_compression_bptc; case GL_PALETTE4_RGB8_OES: case GL_PALETTE4_RGBA8_OES: case GL_PALETTE4_R5_G6_B5_OES: diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index cc109cc52..fdaa68282 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -2038,12 +2038,15 @@ generate_mipmap_compressed(struct gl_context *ctx, GLenum target, components = _mesa_format_num_components(temp_format); - /* Revisit this if we get compressed formats with >8 bits per component */ - if (_mesa_get_format_datatype(srcImage->TexFormat) - == GL_SIGNED_NORMALIZED) { + switch (_mesa_get_format_datatype(srcImage->TexFormat)) { + case GL_FLOAT: + temp_datatype = GL_FLOAT; + break; + case GL_SIGNED_NORMALIZED: + /* Revisit this if we get compressed formats with >8 bits per component */ temp_datatype = GL_BYTE; - } - else { + break; + default: temp_datatype = GL_UNSIGNED_BYTE; } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index e141ac658..cb2a4df4f 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -3529,6 +3529,8 @@ struct gl_constants GLfloat MaxFragmentInterpolationOffset; GLboolean FakeSWMSAA; + + struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES]; }; @@ -3551,11 +3553,13 @@ struct gl_extensions GLboolean ARB_clear_texture; GLboolean ARB_color_buffer_float; GLboolean ARB_compute_shader; + GLboolean ARB_conditional_render_inverted; GLboolean ARB_conservative_depth; GLboolean ARB_copy_image; GLboolean ARB_depth_buffer_float; GLboolean ARB_depth_clamp; GLboolean ARB_depth_texture; + GLboolean ARB_derivative_control; GLboolean ARB_draw_buffers_blend; GLboolean ARB_draw_elements_base_vertex; GLboolean ARB_draw_indirect; @@ -3593,6 +3597,7 @@ struct gl_extensions GLboolean ARB_texture_buffer_object; GLboolean ARB_texture_buffer_object_rgb32; GLboolean ARB_texture_buffer_range; + GLboolean ARB_texture_compression_bptc; GLboolean ARB_texture_compression_rgtc; GLboolean ARB_texture_cube_map; GLboolean ARB_texture_cube_map_array; @@ -4172,8 +4177,6 @@ struct gl_context */ struct gl_pipeline_object *_Shader; - struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES]; - struct gl_query_state Query; /**< occlusion, timer queries */ struct gl_transform_feedback_state TransformFeedback; diff --git a/mesalib/src/mesa/main/pixelstore.c b/mesalib/src/mesa/main/pixelstore.c index 05f6583a4..fc815337b 100644 --- a/mesalib/src/mesa/main/pixelstore.c +++ b/mesalib/src/mesa/main/pixelstore.c @@ -284,3 +284,45 @@ _mesa_init_pixelstore( struct gl_context *ctx ) _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj, ctx->Shared->NullBufferObj); } + + +/** + * Check if the given compressed pixel storage parameters are legal. + * Record a GL error if illegal. + * \return true if legal, false if illegal + */ +bool +_mesa_compressed_pixel_storage_error_check( + struct gl_context *ctx, + GLint dimensions, + const struct gl_pixelstore_attrib *packing, + const char *caller) +{ + if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize) + return true; + + if (packing->CompressedBlockWidth && + packing->SkipPixels % packing->CompressedBlockWidth) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(skip-pixels %% block-width)", caller); + return false; + } + + if (dimensions > 1 && + packing->CompressedBlockHeight && + packing->SkipRows % packing->CompressedBlockHeight) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(skip-rows %% block-height)", caller); + return false; + } + + if (dimensions > 2 && + packing->CompressedBlockDepth && + packing->SkipImages % packing->CompressedBlockDepth) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(skip-images %% block-depth)", caller); + return false; + } + + return true; +} diff --git a/mesalib/src/mesa/main/pixelstore.h b/mesalib/src/mesa/main/pixelstore.h index 1b5347daf..68384548a 100644 --- a/mesalib/src/mesa/main/pixelstore.h +++ b/mesalib/src/mesa/main/pixelstore.h @@ -49,4 +49,12 @@ extern void _mesa_init_pixelstore( struct gl_context *ctx ); +extern bool +_mesa_compressed_pixel_storage_error_check( + struct gl_context *ctx, + GLint dimensions, + const struct gl_pixelstore_attrib *packing, + const char *caller); + + #endif diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index b4a5e7050..620cab3cc 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -119,7 +119,7 @@ _mesa_init_shader_state(struct gl_context *ctx) options.DefaultPragmas.Optimize = GL_TRUE; for (sh = 0; sh < MESA_SHADER_STAGES; ++sh) - memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options)); + memcpy(&ctx->Const.ShaderCompilerOptions[sh], &options, sizeof(options)); ctx->Shader.Flags = _mesa_get_shader_flags(); @@ -826,7 +826,7 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) if (!sh) return; - options = &ctx->ShaderCompilerOptions[sh->Stage]; + options = &ctx->Const.ShaderCompilerOptions[sh->Stage]; /* set default pragma state for shader */ sh->Pragmas = options->DefaultPragmas; diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c index 0189dd296..7ef932ff0 100644 --- a/mesalib/src/mesa/main/shared.c +++ b/mesalib/src/mesa/main/shared.c @@ -113,7 +113,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx) assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); /* Mutex and timestamp for texobj state validation */ - mtx_init(&shared->TexMutex, mtx_plain); + mtx_init(&shared->TexMutex, mtx_recursive); shared->TextureStateStamp = 0; shared->FrameBuffers = _mesa_NewHashTable(); diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 9dbfe9ffe..b4efeee3b 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -42,6 +42,7 @@ #include "texcompress_rgtc.h" #include "texcompress_s3tc.h" #include "texcompress_etc.h" +#include "texcompress_bptc.h" /** @@ -92,6 +93,8 @@ _mesa_gl_compressed_format_base_format(GLenum format) case GL_COMPRESSED_RGB: case GL_COMPRESSED_SRGB: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGB_FXT1_3DFX: case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: @@ -104,8 +107,6 @@ _mesa_gl_compressed_format_base_format(GLenum format) case GL_COMPRESSED_SRGB_ALPHA: case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: - case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: - case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: @@ -235,6 +236,12 @@ _mesa_gl_compressed_format_base_format(GLenum format) * GL_EXT_texture_compression_latc. At the very least, Catalyst 11.6 does not * expose the 3dc formats through this mechanism. * + * The spec for GL_ARB_texture_compression_bptc doesn't mention whether it + * should be included in GL_COMPRESSED_TEXTURE_FORMATS. However as it takes a + * very long time to compress the textures in this format it's probably not + * very useful as a general format where the GL will have to compress it on + * the fly. + * * \param ctx the GL context * \param formats the resulting format list (may be NULL). * @@ -434,6 +441,15 @@ _mesa_glenum_to_compressed_format(GLenum format) case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1; + case GL_COMPRESSED_RGBA_BPTC_UNORM: + return MESA_FORMAT_BPTC_RGBA_UNORM; + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM; + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT; + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT; + default: return MESA_FORMAT_NONE; } @@ -515,6 +531,15 @@ _mesa_compressed_format_to_glenum(struct gl_context *ctx, mesa_format mesaFormat case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: return GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; + case MESA_FORMAT_BPTC_RGBA_UNORM: + return GL_COMPRESSED_RGBA_BPTC_UNORM; + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; + case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: + return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; + case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: + return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; + default: _mesa_problem(ctx, "Unexpected mesa texture format in" " _mesa_compressed_format_to_glenum()"); @@ -586,6 +611,11 @@ _mesa_get_compressed_fetch_func(mesa_format format) return _mesa_get_compressed_rgtc_func(format); case MESA_FORMAT_ETC1_RGB8: return _mesa_get_etc_fetch_func(format); + case MESA_FORMAT_BPTC_RGBA_UNORM: + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: + case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: + return _mesa_get_bptc_fetch_func(format); default: return NULL; } diff --git a/mesalib/src/mesa/main/texcompress_bptc.c b/mesalib/src/mesa/main/texcompress_bptc.c new file mode 100644 index 000000000..9204f123e --- /dev/null +++ b/mesalib/src/mesa/main/texcompress_bptc.c @@ -0,0 +1,1649 @@ +/* + * Copyright (C) 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file texcompress_bptc.c + * GL_ARB_texture_compression_bptc support. + */ + +#include <stdbool.h> +#include "texcompress.h" +#include "texcompress_bptc.h" +#include "util/format_srgb.h" +#include "texstore.h" +#include "macros.h" +#include "image.h" + +#define BLOCK_SIZE 4 +#define N_PARTITIONS 64 +#define BLOCK_BYTES 16 + +struct bptc_unorm_mode { + int n_subsets; + int n_partition_bits; + bool has_rotation_bits; + bool has_index_selection_bit; + int n_color_bits; + int n_alpha_bits; + bool has_endpoint_pbits; + bool has_shared_pbits; + int n_index_bits; + int n_secondary_index_bits; +}; + +struct bptc_float_bitfield { + int8_t endpoint; + uint8_t component; + uint8_t offset; + uint8_t n_bits; + bool reverse; +}; + +struct bptc_float_mode { + bool reserved; + bool transformed_endpoints; + int n_partition_bits; + int n_endpoint_bits; + int n_index_bits; + int n_delta_bits[3]; + struct bptc_float_bitfield bitfields[24]; +}; + +struct bit_writer { + uint8_t buf; + int pos; + uint8_t *dst; +}; + +static const struct bptc_unorm_mode +bptc_unorm_modes[] = { + /* 0 */ { 3, 4, false, false, 4, 0, true, false, 3, 0 }, + /* 1 */ { 2, 6, false, false, 6, 0, false, true, 3, 0 }, + /* 2 */ { 3, 6, false, false, 5, 0, false, false, 2, 0 }, + /* 3 */ { 2, 6, false, false, 7, 0, true, false, 2, 0 }, + /* 4 */ { 1, 0, true, true, 5, 6, false, false, 2, 3 }, + /* 5 */ { 1, 0, true, false, 7, 8, false, false, 2, 2 }, + /* 6 */ { 1, 0, false, false, 7, 7, true, false, 4, 0 }, + /* 7 */ { 2, 6, false, false, 5, 5, true, false, 2, 0 } +}; + +static const struct bptc_float_mode +bptc_float_modes[] = { + /* 00 */ + { false, true, 5, 10, 3, { 5, 5, 5 }, + { { 2, 1, 4, 1, false }, { 2, 2, 4, 1, false }, { 3, 2, 4, 1, false }, + { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false }, + { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, + { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, + { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, + { 3, 2, 3, 1, false }, + { -1 } } + }, + /* 01 */ + { false, true, 5, 7, 3, { 6, 6, 6 }, + { { 2, 1, 5, 1, false }, { 3, 1, 4, 1, false }, { 3, 1, 5, 1, false }, + { 0, 0, 0, 7, false }, { 3, 2, 0, 1, false }, { 3, 2, 1, 1, false }, + { 2, 2, 4, 1, false }, { 0, 1, 0, 7, false }, { 2, 2, 5, 1, false }, + { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false }, { 0, 2, 0, 7, false }, + { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false }, + { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false }, + { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false }, + { 2, 0, 0, 6, false }, + { 3, 0, 0, 6, false }, + { -1 } } + }, + /* 00010 */ + { false, true, 5, 11, 3, { 5, 4, 4 }, + { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 5, false }, { 0, 0, 10, 1, false }, { 2, 1, 0, 4, false }, + { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false }, { 3, 2, 0, 1, false }, + { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false }, + { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false }, + { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false }, + { -1 } } + }, + /* 00011 */ + { false, false, 0, 10, 4, { 10, 10, 10 }, + { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 10, false }, { 1, 1, 0, 10, false }, { 1, 2, 0, 10, false }, + { -1 } } + }, + /* 00110 */ + { false, true, 5, 11, 3, { 4, 5, 4 }, + { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 3, 1, 4, 1, false }, + { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false }, { 0, 1, 10, 1, false }, + { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false }, + { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false }, + { 3, 2, 0, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false }, + { 2, 1, 4, 1, false }, { 3, 2, 3, 1, false }, + { -1 } } + }, + /* 00111 */ + { false, true, 0, 11, 4, { 9, 9, 9 }, + { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 9, false }, { 0, 0, 10, 1, false }, { 1, 1, 0, 9, false }, + { 0, 1, 10, 1, false }, { 1, 2, 0, 9, false }, { 0, 2, 10, 1, false }, + { -1 } } + }, + /* 01010 */ + { false, true, 5, 11, 3, { 4, 4, 5 }, + { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 2, 2, 4, 1, false }, + { 2, 1, 0, 4, false }, { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false }, + { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false }, + { 0, 2, 10, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false }, + { 3, 2, 1, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false }, + { 3, 2, 4, 1, false }, { 3, 2, 3, 1, false }, + { -1 } } + }, + /* 01011 */ + { false, true, 0, 12, 4, { 8, 8, 8 }, + { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 8, false }, { 0, 0, 10, 2, true }, { 1, 1, 0, 8, false }, + { 0, 1, 10, 2, true }, { 1, 2, 0, 8, false }, { 0, 2, 10, 2, true }, + { -1 } } + }, + /* 01110 */ + { false, true, 5, 9, 3, { 5, 5, 5 }, + { { 0, 0, 0, 9, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 9, false }, + { 2, 1, 4, 1, false }, { 0, 2, 0, 9, false }, { 3, 2, 4, 1, false }, + { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false }, + { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, + { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, + { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, + { 3, 2, 3, 1, false }, + { -1 } } + }, + /* 01111 */ + { false, true, 0, 16, 4, { 4, 4, 4 }, + { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false }, + { 1, 0, 0, 4, false }, { 0, 0, 10, 6, true }, { 1, 1, 0, 4, false }, + { 0, 1, 10, 6, true }, { 1, 2, 0, 4, false }, { 0, 2, 10, 6, true }, + { -1 } } + }, + /* 10010 */ + { false, true, 5, 8, 3, { 6, 5, 5 }, + { { 0, 0, 0, 8, false }, { 3, 1, 4, 1, false }, { 2, 2, 4, 1, false }, + { 0, 1, 0, 8, false }, { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false }, + { 0, 2, 0, 8, false }, { 3, 2, 3, 1, false }, { 3, 2, 4, 1, false }, + { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false }, + { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false }, + { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 6, false }, + { 3, 0, 0, 6, false }, + { -1 } } + }, + /* 10011 */ + { true /* reserved */ }, + /* 10110 */ + { false, true, 5, 8, 3, { 5, 6, 5 }, + { { 0, 0, 0, 8, false }, { 3, 2, 0, 1, false }, { 2, 2, 4, 1, false }, + { 0, 1, 0, 8, false }, { 2, 1, 5, 1, false }, { 2, 1, 4, 1, false }, + { 0, 2, 0, 8, false }, { 3, 1, 5, 1, false }, { 3, 2, 4, 1, false }, + { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false }, + { 1, 1, 0, 6, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false }, + { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false }, + { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false }, + { -1 } } + }, + /* 10111 */ + { true /* reserved */ }, + /* 11010 */ + { false, true, 5, 8, 3, { 5, 5, 6 }, + { { 0, 0, 0, 8, false }, { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false }, + { 0, 1, 0, 8, false }, { 2, 2, 5, 1, false }, { 2, 1, 4, 1, false }, + { 0, 2, 0, 8, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false }, + { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false }, + { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, + { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false }, + { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false }, + { -1 } } + }, + /* 11011 */ + { true /* reserved */ }, + /* 11110 */ + { false, false, 5, 6, 3, { 6, 6, 6 }, + { { 0, 0, 0, 6, false }, { 3, 1, 4, 1, false }, { 3, 2, 0, 1, false }, + { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 6, false }, + { 2, 1, 5, 1, false }, { 2, 2, 5, 1, false }, { 3, 2, 2, 1, false }, + { 2, 1, 4, 1, false }, { 0, 2, 0, 6, false }, { 3, 1, 5, 1, false }, + { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false }, + { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false }, + { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false }, + { 2, 0, 0, 6, false }, { 3, 0, 0, 6, false }, + { -1 } } + }, + /* 11111 */ + { true /* reserved */ }, +}; + +/* This partition table is used when the mode has two subsets. Each + * partition is represented by a 32-bit value which gives 2 bits per texel + * within the block. The value of the two bits represents which subset to use + * (0 or 1). + */ +static const uint32_t +partition_table1[N_PARTITIONS] = { + 0x50505050U, 0x40404040U, 0x54545454U, 0x54505040U, + 0x50404000U, 0x55545450U, 0x55545040U, 0x54504000U, + 0x50400000U, 0x55555450U, 0x55544000U, 0x54400000U, + 0x55555440U, 0x55550000U, 0x55555500U, 0x55000000U, + 0x55150100U, 0x00004054U, 0x15010000U, 0x00405054U, + 0x00004050U, 0x15050100U, 0x05010000U, 0x40505054U, + 0x00404050U, 0x05010100U, 0x14141414U, 0x05141450U, + 0x01155440U, 0x00555500U, 0x15014054U, 0x05414150U, + 0x44444444U, 0x55005500U, 0x11441144U, 0x05055050U, + 0x05500550U, 0x11114444U, 0x41144114U, 0x44111144U, + 0x15055054U, 0x01055040U, 0x05041050U, 0x05455150U, + 0x14414114U, 0x50050550U, 0x41411414U, 0x00141400U, + 0x00041504U, 0x00105410U, 0x10541000U, 0x04150400U, + 0x50410514U, 0x41051450U, 0x05415014U, 0x14054150U, + 0x41050514U, 0x41505014U, 0x40011554U, 0x54150140U, + 0x50505500U, 0x00555050U, 0x15151010U, 0x54540404U, +}; + +/* This partition table is used when the mode has three subsets. In this case + * the values can be 0, 1 or 2. + */ +static const uint32_t +partition_table2[N_PARTITIONS] = { + 0xaa685050U, 0x6a5a5040U, 0x5a5a4200U, 0x5450a0a8U, + 0xa5a50000U, 0xa0a05050U, 0x5555a0a0U, 0x5a5a5050U, + 0xaa550000U, 0xaa555500U, 0xaaaa5500U, 0x90909090U, + 0x94949494U, 0xa4a4a4a4U, 0xa9a59450U, 0x2a0a4250U, + 0xa5945040U, 0x0a425054U, 0xa5a5a500U, 0x55a0a0a0U, + 0xa8a85454U, 0x6a6a4040U, 0xa4a45000U, 0x1a1a0500U, + 0x0050a4a4U, 0xaaa59090U, 0x14696914U, 0x69691400U, + 0xa08585a0U, 0xaa821414U, 0x50a4a450U, 0x6a5a0200U, + 0xa9a58000U, 0x5090a0a8U, 0xa8a09050U, 0x24242424U, + 0x00aa5500U, 0x24924924U, 0x24499224U, 0x50a50a50U, + 0x500aa550U, 0xaaaa4444U, 0x66660000U, 0xa5a0a5a0U, + 0x50a050a0U, 0x69286928U, 0x44aaaa44U, 0x66666600U, + 0xaa444444U, 0x54a854a8U, 0x95809580U, 0x96969600U, + 0xa85454a8U, 0x80959580U, 0xaa141414U, 0x96960000U, + 0xaaaa1414U, 0xa05050a0U, 0xa0a5a5a0U, 0x96000000U, + 0x40804080U, 0xa9a8a9a8U, 0xaaaaaa44U, 0x2a4a5254U +}; + +static const uint8_t +anchor_indices[][N_PARTITIONS] = { + /* Anchor index values for the second subset of two-subset partitioning */ + { + 0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, + 0xf,0x2,0x8,0x2,0x2,0x8,0x8,0xf,0x2,0x8,0x2,0x2,0x8,0x8,0x2,0x2, + 0xf,0xf,0x6,0x8,0x2,0x8,0xf,0xf,0x2,0x8,0x2,0x2,0x2,0xf,0xf,0x6, + 0x6,0x2,0x6,0x8,0xf,0xf,0x2,0x2,0xf,0xf,0xf,0xf,0xf,0x2,0x2,0xf + }, + + /* Anchor index values for the second subset of three-subset partitioning */ + { + 0x3,0x3,0xf,0xf,0x8,0x3,0xf,0xf,0x8,0x8,0x6,0x6,0x6,0x5,0x3,0x3, + 0x3,0x3,0x8,0xf,0x3,0x3,0x6,0xa,0x5,0x8,0x8,0x6,0x8,0x5,0xf,0xf, + 0x8,0xf,0x3,0x5,0x6,0xa,0x8,0xf,0xf,0x3,0xf,0x5,0xf,0xf,0xf,0xf, + 0x3,0xf,0x5,0x5,0x5,0x8,0x5,0xa,0x5,0xa,0x8,0xd,0xf,0xc,0x3,0x3 + }, + + /* Anchor index values for the third subset of three-subset + * partitioning + */ + { + 0xf,0x8,0x8,0x3,0xf,0xf,0x3,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8, + 0xf,0x8,0xf,0x3,0xf,0x8,0xf,0x8,0x3,0xf,0x6,0xa,0xf,0xf,0xa,0x8, + 0xf,0x3,0xf,0xa,0xa,0x8,0x9,0xa,0x6,0xf,0x8,0xf,0x3,0x6,0x6,0x8, + 0xf,0x3,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x3,0xf,0xf,0x8 + } +}; + +static int +extract_bits(const uint8_t *block, + int offset, + int n_bits) +{ + int byte_index = offset / 8; + int bit_index = offset % 8; + int n_bits_in_byte = MIN2(n_bits, 8 - bit_index); + int result = 0; + int bit = 0; + + while (true) { + result |= ((block[byte_index] >> bit_index) & + ((1 << n_bits_in_byte) - 1)) << bit; + + n_bits -= n_bits_in_byte; + + if (n_bits <= 0) + return result; + + bit += n_bits_in_byte; + byte_index++; + bit_index = 0; + n_bits_in_byte = MIN2(n_bits, 8); + } +} + +static uint8_t +expand_component(uint8_t byte, + int n_bits) +{ + /* Expands a n-bit quantity into a byte by copying the most-significant + * bits into the unused least-significant bits. + */ + return byte << (8 - n_bits) | (byte >> (2 * n_bits - 8)); +} + +static int +extract_unorm_endpoints(const struct bptc_unorm_mode *mode, + const uint8_t *block, + int bit_offset, + uint8_t endpoints[][4]) +{ + int component; + int subset; + int endpoint; + int pbit; + int n_components; + + /* Extract each color component */ + for (component = 0; component < 3; component++) { + for (subset = 0; subset < mode->n_subsets; subset++) { + for (endpoint = 0; endpoint < 2; endpoint++) { + endpoints[subset * 2 + endpoint][component] = + extract_bits(block, bit_offset, mode->n_color_bits); + bit_offset += mode->n_color_bits; + } + } + } + + /* Extract the alpha values */ + if (mode->n_alpha_bits > 0) { + for (subset = 0; subset < mode->n_subsets; subset++) { + for (endpoint = 0; endpoint < 2; endpoint++) { + endpoints[subset * 2 + endpoint][3] = + extract_bits(block, bit_offset, mode->n_alpha_bits); + bit_offset += mode->n_alpha_bits; + } + } + + n_components = 4; + } else { + for (subset = 0; subset < mode->n_subsets; subset++) + for (endpoint = 0; endpoint < 2; endpoint++) + endpoints[subset * 2 + endpoint][3] = 255; + + n_components = 3; + } + + /* Add in the p-bits */ + if (mode->has_endpoint_pbits) { + for (subset = 0; subset < mode->n_subsets; subset++) { + for (endpoint = 0; endpoint < 2; endpoint++) { + pbit = extract_bits(block, bit_offset, 1); + bit_offset += 1; + + for (component = 0; component < n_components; component++) { + endpoints[subset * 2 + endpoint][component] <<= 1; + endpoints[subset * 2 + endpoint][component] |= pbit; + } + } + } + } else if (mode->has_shared_pbits) { + for (subset = 0; subset < mode->n_subsets; subset++) { + pbit = extract_bits(block, bit_offset, 1); + bit_offset += 1; + + for (endpoint = 0; endpoint < 2; endpoint++) { + for (component = 0; component < n_components; component++) { + endpoints[subset * 2 + endpoint][component] <<= 1; + endpoints[subset * 2 + endpoint][component] |= pbit; + } + } + } + } + + /* Expand the n-bit values to a byte */ + for (subset = 0; subset < mode->n_subsets; subset++) { + for (endpoint = 0; endpoint < 2; endpoint++) { + for (component = 0; component < 3; component++) { + endpoints[subset * 2 + endpoint][component] = + expand_component(endpoints[subset * 2 + endpoint][component], + mode->n_color_bits + + mode->has_endpoint_pbits + + mode->has_shared_pbits); + } + + if (mode->n_alpha_bits > 0) { + endpoints[subset * 2 + endpoint][3] = + expand_component(endpoints[subset * 2 + endpoint][3], + mode->n_alpha_bits + + mode->has_endpoint_pbits + + mode->has_shared_pbits); + } + } + } + + return bit_offset; +} + +static bool +is_anchor(int n_subsets, + int partition_num, + int texel) +{ + if (texel == 0) + return true; + + switch (n_subsets) { + case 1: + return false; + case 2: + return anchor_indices[0][partition_num] == texel; + case 3: + return (anchor_indices[1][partition_num] == texel || + anchor_indices[2][partition_num] == texel); + default: + assert(false); + return false; + } +} + +static int +count_anchors_before_texel(int n_subsets, + int partition_num, + int texel) +{ + int count = 1; + + if (texel == 0) + return 0; + + switch (n_subsets) { + case 1: + break; + case 2: + if (texel > anchor_indices[0][partition_num]) + count++; + break; + case 3: + if (texel > anchor_indices[1][partition_num]) + count++; + if (texel > anchor_indices[2][partition_num]) + count++; + break; + default: + assert(false); + return 0; + } + + return count; +} + +static int32_t +interpolate(int32_t a, int32_t b, + int index, + int index_bits) +{ + static const uint8_t weights2[] = { 0, 21, 43, 64 }; + static const uint8_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + static const uint8_t weights4[] = + { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; + static const uint8_t *weights[] = { + NULL, NULL, weights2, weights3, weights4 + }; + int weight; + + weight = weights[index_bits][index]; + + return ((64 - weight) * a + weight * b + 32) >> 6; +} + +static void +apply_rotation(int rotation, + uint8_t *result) +{ + uint8_t t; + + if (rotation == 0) + return; + + rotation--; + + t = result[rotation]; + result[rotation] = result[3]; + result[3] = t; +} + +static void +fetch_rgba_unorm_from_block(const uint8_t *block, + uint8_t *result, + int texel) +{ + int mode_num = ffs(block[0]); + const struct bptc_unorm_mode *mode; + int bit_offset, secondary_bit_offset; + int partition_num; + int subset_num; + int rotation; + int index_selection; + int index_bits; + int indices[2]; + int index; + int anchors_before_texel; + bool anchor; + uint8_t endpoints[3 * 2][4]; + uint32_t subsets; + int component; + + if (mode_num == 0) { + /* According to the spec this mode is reserved and shouldn't be used. */ + memset(result, 0, 3); + result[3] = 0xff; + return; + } + + mode = bptc_unorm_modes + mode_num - 1; + bit_offset = mode_num; + + partition_num = extract_bits(block, bit_offset, mode->n_partition_bits); + bit_offset += mode->n_partition_bits; + + switch (mode->n_subsets) { + case 1: + subsets = 0; + break; + case 2: + subsets = partition_table1[partition_num]; + break; + case 3: + subsets = partition_table2[partition_num]; + break; + default: + assert(false); + return; + } + + if (mode->has_rotation_bits) { + rotation = extract_bits(block, bit_offset, 2); + bit_offset += 2; + } else { + rotation = 0; + } + + if (mode->has_index_selection_bit) { + index_selection = extract_bits(block, bit_offset, 1); + bit_offset++; + } else { + index_selection = 0; + } + + bit_offset = extract_unorm_endpoints(mode, block, bit_offset, endpoints); + + anchors_before_texel = count_anchors_before_texel(mode->n_subsets, + partition_num, texel); + + /* Calculate the offset to the secondary index */ + secondary_bit_offset = (bit_offset + + BLOCK_SIZE * BLOCK_SIZE * mode->n_index_bits - + mode->n_subsets + + mode->n_secondary_index_bits * texel - + anchors_before_texel); + + /* Calculate the offset to the primary index for this texel */ + bit_offset += mode->n_index_bits * texel - anchors_before_texel; + + subset_num = (subsets >> (texel * 2)) & 3; + + anchor = is_anchor(mode->n_subsets, partition_num, texel); + + index_bits = mode->n_index_bits; + if (anchor) + index_bits--; + indices[0] = extract_bits(block, bit_offset, index_bits); + + if (mode->n_secondary_index_bits) { + index_bits = mode->n_secondary_index_bits; + if (anchor) + index_bits--; + indices[1] = extract_bits(block, secondary_bit_offset, index_bits); + } + + index = indices[index_selection]; + index_bits = (index_selection ? + mode->n_secondary_index_bits : + mode->n_index_bits); + + for (component = 0; component < 3; component++) + result[component] = interpolate(endpoints[subset_num * 2][component], + endpoints[subset_num * 2 + 1][component], + index, + index_bits); + + /* Alpha uses the opposite index from the color components */ + if (mode->n_secondary_index_bits && !index_selection) { + index = indices[1]; + index_bits = mode->n_secondary_index_bits; + } else { + index = indices[0]; + index_bits = mode->n_index_bits; + } + + result[3] = interpolate(endpoints[subset_num * 2][3], + endpoints[subset_num * 2 + 1][3], + index, + index_bits); + + apply_rotation(rotation, result); +} + +static void +fetch_bptc_rgba_unorm_bytes(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLubyte *texel) +{ + const GLubyte *block; + + block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + + fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4); +} + +static void +fetch_bptc_rgba_unorm(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLfloat *texel) +{ + GLubyte texel_bytes[4]; + + fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); + + texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]); + texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]); + texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); +} + +static void +fetch_bptc_srgb_alpha_unorm(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLfloat *texel) +{ + GLubyte texel_bytes[4]; + + fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes); + + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]); +} + +static int32_t +sign_extend(int32_t value, + int n_bits) +{ + if ((value & (1 << (n_bits - 1)))) { + value |= (~(int32_t) 0) << n_bits; + } + + return value; +} + +static int +signed_unquantize(int value, int n_endpoint_bits) +{ + bool sign; + + if (n_endpoint_bits >= 16) + return value; + + if (value == 0) + return 0; + + sign = false; + + if (value < 0) { + sign = true; + value = -value; + } + + if (value >= (1 << (n_endpoint_bits - 1)) - 1) + value = 0x7fff; + else + value = ((value << 15) + 0x4000) >> (n_endpoint_bits - 1); + + if (sign) + value = -value; + + return value; +} + +static int +unsigned_unquantize(int value, int n_endpoint_bits) +{ + if (n_endpoint_bits >= 15) + return value; + + if (value == 0) + return 0; + + if (value == (1 << n_endpoint_bits) - 1) + return 0xffff; + + return ((value << 15) + 0x4000) >> (n_endpoint_bits - 1); +} + +static int +extract_float_endpoints(const struct bptc_float_mode *mode, + const uint8_t *block, + int bit_offset, + int32_t endpoints[][3], + bool is_signed) +{ + const struct bptc_float_bitfield *bitfield; + int endpoint, component; + int n_endpoints; + int value; + int i; + + if (mode->n_partition_bits) + n_endpoints = 4; + else + n_endpoints = 2; + + memset(endpoints, 0, sizeof endpoints[0][0] * n_endpoints * 3); + + for (bitfield = mode->bitfields; bitfield->endpoint != -1; bitfield++) { + value = extract_bits(block, bit_offset, bitfield->n_bits); + bit_offset += bitfield->n_bits; + + if (bitfield->reverse) { + for (i = 0; i < bitfield->n_bits; i++) { + if (value & (1 << i)) + endpoints[bitfield->endpoint][bitfield->component] |= + 1 << ((bitfield->n_bits - 1 - i) + bitfield->offset); + } + } else { + endpoints[bitfield->endpoint][bitfield->component] |= + value << bitfield->offset; + } + } + + if (mode->transformed_endpoints) { + /* The endpoints are specified as signed offsets from e0 */ + for (endpoint = 1; endpoint < n_endpoints; endpoint++) { + for (component = 0; component < 3; component++) { + value = sign_extend(endpoints[endpoint][component], + mode->n_delta_bits[component]); + endpoints[endpoint][component] = + ((endpoints[0][component] + value) & + ((1 << mode->n_endpoint_bits) - 1)); + } + } + } + + if (is_signed) { + for (endpoint = 0; endpoint < n_endpoints; endpoint++) { + for (component = 0; component < 3; component++) { + value = sign_extend(endpoints[endpoint][component], + mode->n_endpoint_bits); + endpoints[endpoint][component] = + signed_unquantize(value, mode->n_endpoint_bits); + } + } + } else { + for (endpoint = 0; endpoint < n_endpoints; endpoint++) { + for (component = 0; component < 3; component++) { + endpoints[endpoint][component] = + unsigned_unquantize(endpoints[endpoint][component], + mode->n_endpoint_bits); + } + } + } + + return bit_offset; +} + +static int32_t +finish_unsigned_unquantize(int32_t value) +{ + return value * 31 / 64; +} + +static int32_t +finish_signed_unquantize(int32_t value) +{ + if (value < 0) + return (-value * 31 / 32) | 0x8000; + else + return value * 31 / 32; +} + +static void +fetch_rgb_float_from_block(const uint8_t *block, + float *result, + int texel, + bool is_signed) +{ + int mode_num; + const struct bptc_float_mode *mode; + int bit_offset; + int partition_num; + int subset_num; + int index_bits; + int index; + int anchors_before_texel; + int32_t endpoints[2 * 2][3]; + uint32_t subsets; + int n_subsets; + int component; + int32_t value; + + if (block[0] & 0x2) { + mode_num = (((block[0] >> 1) & 0xe) | (block[0] & 1)) + 2; + bit_offset = 5; + } else { + mode_num = block[0] & 3; + bit_offset = 2; + } + + mode = bptc_float_modes + mode_num; + + if (mode->reserved) { + memset(result, 0, sizeof result[0] * 3); + result[3] = 1.0f; + return; + } + + bit_offset = extract_float_endpoints(mode, block, bit_offset, + endpoints, is_signed); + + if (mode->n_partition_bits) { + partition_num = extract_bits(block, bit_offset, mode->n_partition_bits); + bit_offset += mode->n_partition_bits; + + subsets = partition_table1[partition_num]; + n_subsets = 2; + } else { + partition_num = 0; + subsets = 0; + n_subsets = 1; + } + + anchors_before_texel = + count_anchors_before_texel(n_subsets, partition_num, texel); + + /* Calculate the offset to the primary index for this texel */ + bit_offset += mode->n_index_bits * texel - anchors_before_texel; + + subset_num = (subsets >> (texel * 2)) & 3; + + index_bits = mode->n_index_bits; + if (is_anchor(n_subsets, partition_num, texel)) + index_bits--; + index = extract_bits(block, bit_offset, index_bits); + + for (component = 0; component < 3; component++) { + value = interpolate(endpoints[subset_num * 2][component], + endpoints[subset_num * 2 + 1][component], + index, + mode->n_index_bits); + + if (is_signed) + value = finish_signed_unquantize(value); + else + value = finish_unsigned_unquantize(value); + + result[component] = _mesa_half_to_float(value); + } + + result[3] = 1.0f; +} + +static void +fetch_bptc_rgb_float(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLfloat *texel, + bool is_signed) +{ + const GLubyte *block; + + block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + + fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed); +} + +static void +fetch_bptc_rgb_signed_float(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLfloat *texel) +{ + fetch_bptc_rgb_float(map, rowStride, i, j, texel, true); +} + +static void +fetch_bptc_rgb_unsigned_float(const GLubyte *map, + GLint rowStride, GLint i, GLint j, + GLfloat *texel) +{ + fetch_bptc_rgb_float(map, rowStride, i, j, texel, false); +} + +compressed_fetch_func +_mesa_get_bptc_fetch_func(mesa_format format) +{ + switch (format) { + case MESA_FORMAT_BPTC_RGBA_UNORM: + return fetch_bptc_rgba_unorm; + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + return fetch_bptc_srgb_alpha_unorm; + case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: + return fetch_bptc_rgb_signed_float; + case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: + return fetch_bptc_rgb_unsigned_float; + default: + return NULL; + } +} + +static void +write_bits(struct bit_writer *writer, int n_bits, int value) +{ + do { + if (n_bits + writer->pos >= 8) { + *(writer->dst++) = writer->buf | (value << writer->pos); + writer->buf = 0; + value >>= (8 - writer->pos); + n_bits -= (8 - writer->pos); + writer->pos = 0; + } else { + writer->buf |= value << writer->pos; + writer->pos += n_bits; + break; + } + } while (n_bits > 0); +} + +static void +get_average_luminance_alpha_unorm(int width, int height, + const uint8_t *src, int src_rowstride, + int *average_luminance, int *average_alpha) +{ + int luminance_sum = 0, alpha_sum = 0; + int y, x; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + luminance_sum += src[0] + src[1] + src[2]; + alpha_sum += src[3]; + src += 4; + } + src += src_rowstride - width * 4; + } + + *average_luminance = luminance_sum / (width * height); + *average_alpha = alpha_sum / (width * height); +} + +static void +get_rgba_endpoints_unorm(int width, int height, + const uint8_t *src, int src_rowstride, + int average_luminance, int average_alpha, + uint8_t endpoints[][4]) +{ + int endpoint_luminances[2]; + int midpoint; + int sums[2][4]; + int endpoint; + int luminance; + uint8_t temp[3]; + const uint8_t *p = src; + int rgb_left_endpoint_count = 0; + int alpha_left_endpoint_count = 0; + int y, x, i; + + memset(sums, 0, sizeof sums); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + luminance = p[0] + p[1] + p[2]; + if (luminance < average_luminance) { + endpoint = 0; + rgb_left_endpoint_count++; + } else { + endpoint = 1; + } + for (i = 0; i < 3; i++) + sums[endpoint][i] += p[i]; + + if (p[2] < average_alpha) { + endpoint = 0; + alpha_left_endpoint_count++; + } else { + endpoint = 1; + } + sums[endpoint][3] += p[3]; + + p += 4; + } + + p += src_rowstride - width * 4; + } + + if (rgb_left_endpoint_count == 0 || + rgb_left_endpoint_count == width * height) { + for (i = 0; i < 3; i++) + endpoints[0][i] = endpoints[1][i] = + (sums[0][i] + sums[1][i]) / (width * height); + } else { + for (i = 0; i < 3; i++) { + endpoints[0][i] = sums[0][i] / rgb_left_endpoint_count; + endpoints[1][i] = (sums[1][i] / + (width * height - rgb_left_endpoint_count)); + } + } + + if (alpha_left_endpoint_count == 0 || + alpha_left_endpoint_count == width * height) { + endpoints[0][3] = endpoints[1][3] = + (sums[0][3] + sums[1][3]) / (width * height); + } else { + endpoints[0][3] = sums[0][3] / alpha_left_endpoint_count; + endpoints[1][3] = (sums[1][3] / + (width * height - alpha_left_endpoint_count)); + } + + /* We may need to swap the endpoints to ensure the most-significant bit of + * the first index is zero */ + + for (endpoint = 0; endpoint < 2; endpoint++) { + endpoint_luminances[endpoint] = + endpoints[endpoint][0] + + endpoints[endpoint][1] + + endpoints[endpoint][2]; + } + midpoint = (endpoint_luminances[0] + endpoint_luminances[1]) / 2; + + if ((src[0] + src[1] + src[2] <= midpoint) != + (endpoint_luminances[0] <= midpoint)) { + memcpy(temp, endpoints[0], 3); + memcpy(endpoints[0], endpoints[1], 3); + memcpy(endpoints[1], temp, 3); + } + + /* Same for the alpha endpoints */ + + midpoint = (endpoints[0][3] + endpoints[1][3]) / 2; + + if ((src[3] <= midpoint) != (endpoints[0][3] <= midpoint)) { + temp[0] = endpoints[0][3]; + endpoints[0][3] = endpoints[1][3]; + endpoints[1][3] = temp[0]; + } +} + +static void +write_rgb_indices_unorm(struct bit_writer *writer, + int src_width, int src_height, + const uint8_t *src, int src_rowstride, + uint8_t endpoints[][4]) +{ + int luminance; + int endpoint_luminances[2]; + int endpoint; + int index; + int y, x; + + for (endpoint = 0; endpoint < 2; endpoint++) { + endpoint_luminances[endpoint] = + endpoints[endpoint][0] + + endpoints[endpoint][1] + + endpoints[endpoint][2]; + } + + /* If the endpoints have the same luminance then we'll just use index 0 for + * all of the texels */ + if (endpoint_luminances[0] == endpoint_luminances[1]) { + write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 2 - 1, 0); + return; + } + + for (y = 0; y < src_height; y++) { + for (x = 0; x < src_width; x++) { + luminance = src[0] + src[1] + src[2]; + + index = ((luminance - endpoint_luminances[0]) * 3 / + (endpoint_luminances[1] - endpoint_luminances[0])); + if (index < 0) + index = 0; + else if (index > 3) + index = 3; + + assert(x != 0 || y != 0 || index < 2); + + write_bits(writer, (x == 0 && y == 0) ? 1 : 2, index); + + src += 4; + } + + /* Pad the indices out to the block size */ + if (src_width < BLOCK_SIZE) + write_bits(writer, 2 * (BLOCK_SIZE - src_width), 0); + + src += src_rowstride - src_width * 4; + } + + /* Pad the indices out to the block size */ + if (src_height < BLOCK_SIZE) + write_bits(writer, 2 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0); +} + +static void +write_alpha_indices_unorm(struct bit_writer *writer, + int src_width, int src_height, + const uint8_t *src, int src_rowstride, + uint8_t endpoints[][4]) +{ + int index; + int y, x; + + /* If the endpoints have the same alpha then we'll just use index 0 for + * all of the texels */ + if (endpoints[0][3] == endpoints[1][3]) { + write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 3 - 1, 0); + return; + } + + for (y = 0; y < src_height; y++) { + for (x = 0; x < src_width; x++) { + index = (((int) src[3] - (int) endpoints[0][3]) * 7 / + ((int) endpoints[1][3] - endpoints[0][3])); + if (index < 0) + index = 0; + else if (index > 7) + index = 7; + + assert(x != 0 || y != 0 || index < 4); + + /* The first index has one less bit */ + write_bits(writer, (x == 0 && y == 0) ? 2 : 3, index); + + src += 4; + } + + /* Pad the indices out to the block size */ + if (src_width < BLOCK_SIZE) + write_bits(writer, 3 * (BLOCK_SIZE - src_width), 0); + + src += src_rowstride - src_width * 4; + } + + /* Pad the indices out to the block size */ + if (src_height < BLOCK_SIZE) + write_bits(writer, 3 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0); +} + +static void +compress_rgba_unorm_block(int src_width, int src_height, + const uint8_t *src, int src_rowstride, + uint8_t *dst) +{ + int average_luminance, average_alpha; + uint8_t endpoints[2][4]; + struct bit_writer writer; + int component, endpoint; + + get_average_luminance_alpha_unorm(src_width, src_height, src, src_rowstride, + &average_luminance, &average_alpha); + get_rgba_endpoints_unorm(src_width, src_height, src, src_rowstride, + average_luminance, average_alpha, + endpoints); + + writer.dst = dst; + writer.pos = 0; + writer.buf = 0; + + write_bits(&writer, 5, 0x10); /* mode 4 */ + write_bits(&writer, 2, 0); /* rotation 0 */ + write_bits(&writer, 1, 0); /* index selection bit */ + + /* Write the color endpoints */ + for (component = 0; component < 3; component++) + for (endpoint = 0; endpoint < 2; endpoint++) + write_bits(&writer, 5, endpoints[endpoint][component] >> 3); + + /* Write the alpha endpoints */ + for (endpoint = 0; endpoint < 2; endpoint++) + write_bits(&writer, 6, endpoints[endpoint][3] >> 2); + + write_rgb_indices_unorm(&writer, + src_width, src_height, + src, src_rowstride, + endpoints); + write_alpha_indices_unorm(&writer, + src_width, src_height, + src, src_rowstride, + endpoints); +} + +static void +compress_rgba_unorm(int width, int height, + const uint8_t *src, int src_rowstride, + uint8_t *dst, int dst_rowstride) +{ + int dst_row_diff; + int y, x; + + if (dst_rowstride >= width * 4) + dst_row_diff = dst_rowstride - ((width + 3) & ~3) * 4; + else + dst_row_diff = 0; + + for (y = 0; y < height; y += BLOCK_SIZE) { + for (x = 0; x < width; x += BLOCK_SIZE) { + compress_rgba_unorm_block(MIN2(width - x, BLOCK_SIZE), + MIN2(height - y, BLOCK_SIZE), + src + x * 4 + y * src_rowstride, + src_rowstride, + dst); + dst += BLOCK_BYTES; + } + dst += dst_row_diff; + } +} + +GLboolean +_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS) +{ + const GLubyte *pixels; + const GLubyte *tempImage = NULL; + GLenum baseFormat; + int rowstride; + + if (srcFormat != GL_RGBA || + srcType != GL_UNSIGNED_BYTE || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGBA/ubyte */ + baseFormat = _mesa_get_format_base_format(dstFormat); + tempImage = _mesa_make_temp_ubyte_image(ctx, dims, + baseInternalFormat, + baseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + if (!tempImage) + return GL_FALSE; /* out of memory */ + + pixels = tempImage; + rowstride = srcWidth * 4; + } else { + pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, + srcFormat, srcType, 0, 0); + rowstride = _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, srcType); + } + + compress_rgba_unorm(srcWidth, srcHeight, + pixels, rowstride, + dstSlices[0], dstRowStride); + + free((void *) tempImage); + + return GL_TRUE; +} + +static float +get_average_luminance_float(int width, int height, + const float *src, int src_rowstride) +{ + float luminance_sum = 0; + int y, x; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + luminance_sum += src[0] + src[1] + src[2]; + src += 3; + } + src += (src_rowstride - width * 3 * sizeof (float)) / sizeof (float); + } + + return luminance_sum / (width * height); +} + +static float +clamp_value(float value, bool is_signed) +{ + if (value > 65504.0f) + return 65504.0f; + + if (is_signed) { + if (value < -65504.0f) + return -65504.0f; + else + return value; + } + + if (value < 0.0f) + return 0.0f; + + return value; +} + +static void +get_endpoints_float(int width, int height, + const float *src, int src_rowstride, + float average_luminance, float endpoints[][3], + bool is_signed) +{ + float endpoint_luminances[2]; + float midpoint; + float sums[2][3]; + int endpoint, component; + float luminance; + float temp[3]; + const float *p = src; + int left_endpoint_count = 0; + int y, x, i; + + memset(sums, 0, sizeof sums); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + luminance = p[0] + p[1] + p[2]; + if (luminance < average_luminance) { + endpoint = 0; + left_endpoint_count++; + } else { + endpoint = 1; + } + for (i = 0; i < 3; i++) + sums[endpoint][i] += p[i]; + + p += 3; + } + + p += (src_rowstride - width * 3 * sizeof (float)) / sizeof (float); + } + + if (left_endpoint_count == 0 || + left_endpoint_count == width * height) { + for (i = 0; i < 3; i++) + endpoints[0][i] = endpoints[1][i] = + (sums[0][i] + sums[1][i]) / (width * height); + } else { + for (i = 0; i < 3; i++) { + endpoints[0][i] = sums[0][i] / left_endpoint_count; + endpoints[1][i] = sums[1][i] / (width * height - left_endpoint_count); + } + } + + /* Clamp the endpoints to the range of a half float and strip out + * infinities */ + for (endpoint = 0; endpoint < 2; endpoint++) { + for (component = 0; component < 3; component++) { + endpoints[endpoint][component] = + clamp_value(endpoints[endpoint][component], is_signed); + } + } + + /* We may need to swap the endpoints to ensure the most-significant bit of + * the first index is zero */ + + for (endpoint = 0; endpoint < 2; endpoint++) { + endpoint_luminances[endpoint] = + endpoints[endpoint][0] + + endpoints[endpoint][1] + + endpoints[endpoint][2]; + } + midpoint = (endpoint_luminances[0] + endpoint_luminances[1]) / 2.0f; + + if ((src[0] + src[1] + src[2] <= midpoint) != + (endpoint_luminances[0] <= midpoint)) { + memcpy(temp, endpoints[0], sizeof temp); + memcpy(endpoints[0], endpoints[1], sizeof temp); + memcpy(endpoints[1], temp, sizeof temp); + } +} + +static void +write_rgb_indices_float(struct bit_writer *writer, + int src_width, int src_height, + const float *src, int src_rowstride, + float endpoints[][3]) +{ + float luminance; + float endpoint_luminances[2]; + int endpoint; + int index; + int y, x; + + for (endpoint = 0; endpoint < 2; endpoint++) { + endpoint_luminances[endpoint] = + endpoints[endpoint][0] + + endpoints[endpoint][1] + + endpoints[endpoint][2]; + } + + /* If the endpoints have the same luminance then we'll just use index 0 for + * all of the texels */ + if (endpoint_luminances[0] == endpoint_luminances[1]) { + write_bits(writer, BLOCK_SIZE * BLOCK_SIZE * 4 - 1, 0); + return; + } + + for (y = 0; y < src_height; y++) { + for (x = 0; x < src_width; x++) { + luminance = src[0] + src[1] + src[2]; + + index = ((luminance - endpoint_luminances[0]) * 15 / + (endpoint_luminances[1] - endpoint_luminances[0])); + if (index < 0) + index = 0; + else if (index > 15) + index = 15; + + assert(x != 0 || y != 0 || index < 8); + + write_bits(writer, (x == 0 && y == 0) ? 3 : 4, index); + + src += 3; + } + + /* Pad the indices out to the block size */ + if (src_width < BLOCK_SIZE) + write_bits(writer, 4 * (BLOCK_SIZE - src_width), 0); + + src += (src_rowstride - src_width * 3 * sizeof (float)) / sizeof (float); + } + + /* Pad the indices out to the block size */ + if (src_height < BLOCK_SIZE) + write_bits(writer, 4 * BLOCK_SIZE * (BLOCK_SIZE - src_height), 0); +} + +static int +get_endpoint_value(float value, bool is_signed) +{ + bool sign = false; + int half; + + if (is_signed) { + half = _mesa_float_to_half(value); + + if (half & 0x8000) { + half &= 0x7fff; + sign = true; + } + + half = (32 * half / 31) >> 6; + + if (sign) + half = -half & ((1 << 10) - 1); + + return half; + } else { + if (value <= 0.0f) + return 0; + + half = _mesa_float_to_half(value); + + return (64 * half / 31) >> 6; + } +} + +static void +compress_rgb_float_block(int src_width, int src_height, + const float *src, int src_rowstride, + uint8_t *dst, + bool is_signed) +{ + float average_luminance; + float endpoints[2][3]; + struct bit_writer writer; + int component, endpoint; + int endpoint_value; + + average_luminance = + get_average_luminance_float(src_width, src_height, src, src_rowstride); + get_endpoints_float(src_width, src_height, src, src_rowstride, + average_luminance, endpoints, is_signed); + + writer.dst = dst; + writer.pos = 0; + writer.buf = 0; + + write_bits(&writer, 5, 3); /* mode 3 */ + + /* Write the endpoints */ + for (endpoint = 0; endpoint < 2; endpoint++) { + for (component = 0; component < 3; component++) { + endpoint_value = + get_endpoint_value(endpoints[endpoint][component], is_signed); + write_bits(&writer, 10, endpoint_value); + } + } + + write_rgb_indices_float(&writer, + src_width, src_height, + src, src_rowstride, + endpoints); +} + +static void +compress_rgb_float(int width, int height, + const float *src, int src_rowstride, + uint8_t *dst, int dst_rowstride, + bool is_signed) +{ + int dst_row_diff; + int y, x; + + if (dst_rowstride >= width * 4) + dst_row_diff = dst_rowstride - ((width + 3) & ~3) * 4; + else + dst_row_diff = 0; + + for (y = 0; y < height; y += BLOCK_SIZE) { + for (x = 0; x < width; x += BLOCK_SIZE) { + compress_rgb_float_block(MIN2(width - x, BLOCK_SIZE), + MIN2(height - y, BLOCK_SIZE), + src + x * 3 + + y * src_rowstride / sizeof (float), + src_rowstride, + dst, + is_signed); + dst += BLOCK_BYTES; + } + dst += dst_row_diff; + } +} + +static GLboolean +texstore_bptc_rgb_float(TEXSTORE_PARAMS, + bool is_signed) +{ + const float *pixels; + const float *tempImage = NULL; + GLenum baseFormat; + int rowstride; + + if (srcFormat != GL_RGB || + srcType != GL_FLOAT || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGB/float */ + baseFormat = _mesa_get_format_base_format(dstFormat); + tempImage = _mesa_make_temp_float_image(ctx, dims, + baseInternalFormat, + baseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking, + ctx->_ImageTransferState); + if (!tempImage) + return GL_FALSE; /* out of memory */ + + pixels = tempImage; + rowstride = srcWidth * sizeof(float) * 3; + } else { + pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, + srcFormat, srcType, 0, 0); + rowstride = _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, srcType); + } + + compress_rgb_float(srcWidth, srcHeight, + pixels, rowstride, + dstSlices[0], dstRowStride, + is_signed); + + free((void *) tempImage); + + return GL_TRUE; +} + +GLboolean +_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS) +{ + ASSERT(dstFormat == MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT); + + return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, + srcAddr, srcPacking, + true /* signed */); +} + +GLboolean +_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS) +{ + ASSERT(dstFormat == MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT); + + return texstore_bptc_rgb_float(ctx, dims, baseInternalFormat, + dstFormat, dstRowStride, dstSlices, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, + srcAddr, srcPacking, + false /* unsigned */); +} diff --git a/mesalib/src/mesa/main/texcompress_bptc.h b/mesalib/src/mesa/main/texcompress_bptc.h new file mode 100644 index 000000000..814548e2b --- /dev/null +++ b/mesalib/src/mesa/main/texcompress_bptc.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef TEXCOMPRESS_BPTC_H +#define TEXCOMPRESS_BPTC_H + +#include <inttypes.h> +#include "glheader.h" +#include "texcompress.h" +#include "texstore.h" + +GLboolean +_mesa_texstore_bptc_rgba_unorm(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_bptc_rgb_signed_float(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_bptc_rgb_unsigned_float(TEXSTORE_PARAMS); + +compressed_fetch_func +_mesa_get_bptc_fetch_func(mesa_format format); + +#endif diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index c61a74859..6d3b80556 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -345,6 +345,14 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, return MESA_FORMAT_SRGBA_DXT3; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return MESA_FORMAT_SRGBA_DXT5; + case GL_COMPRESSED_RGBA_BPTC_UNORM: + return MESA_FORMAT_BPTC_RGBA_UNORM; + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM; + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT; + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT; case GL_ALPHA16F_ARB: RETURN_IF_SUPPORTED(MESA_FORMAT_A_FLOAT16); diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index f1e09c986..2c54e4a35 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -40,6 +40,7 @@ #include "mtypes.h" #include "pack.h" #include "pbo.h" +#include "pixelstore.h" #include "texcompress.h" #include "texgetimage.h" #include "teximage.h" @@ -693,7 +694,7 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, GLuint i, slice; GLubyte *dest; - _mesa_compute_compressed_pixelstore(dimensions, texImage, + _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth, &ctx->Pack, @@ -1008,9 +1009,9 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, /* Check for invalid pixel storage modes */ dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); - if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions, - &ctx->Pack, - "glGetCompressedTexImageARB")) { + if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, + &ctx->Pack, + "glGetCompressedTexImageARB")) { return GL_TRUE; } diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index bb050b188..647d28ab3 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -41,6 +41,7 @@ #include "imports.h" #include "macros.h" #include "multisample.h" +#include "pixelstore.h" #include "state.h" #include "texcompress.h" #include "texcompress_cpal.h" @@ -520,6 +521,20 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } } + if (_mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_texture_compression_bptc) { + switch (internalFormat) { + case GL_COMPRESSED_RGBA_BPTC_UNORM: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + return GL_RGBA; + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + return GL_RGB; + default: + ; /* fallthrough */ + } + } + if (ctx->API == API_OPENGLES) { switch (internalFormat) { case GL_PALETTE4_RGB8_OES: @@ -2250,36 +2265,6 @@ texture_error_check( struct gl_context *ctx, } -bool -_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx, - GLint dimensions, - struct gl_pixelstore_attrib *packing, - const char *caller) -{ - if (!_mesa_is_desktop_gl(ctx) || !packing->CompressedBlockSize) - return true; - - if (packing->CompressedBlockWidth && packing->SkipPixels % packing->CompressedBlockWidth) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(skip-pixels %% block-width)", caller); - return false; - } - - if (dimensions > 1 && packing->CompressedBlockHeight && packing->SkipRows % packing->CompressedBlockHeight) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(skip-rows %% block-height)", caller); - return false; - } - - if (dimensions > 2 && packing->CompressedBlockDepth && packing->SkipImages % packing->CompressedBlockDepth) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(skip-images %% block-depth)", caller); - return false; - } - - return true; -} - /** * Error checking for glCompressedTexImage[123]D(). * Note that the width, height and depth values are not fully error checked @@ -2389,9 +2374,9 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, } /* Check for invalid pixel storage modes */ - if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions, - &ctx->Unpack, - "glCompressedTexImage")) { + if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, + &ctx->Unpack, + "glCompressedTexImage")) { return GL_FALSE; } @@ -4197,9 +4182,9 @@ out: /** * Error checking for glCompressedTexSubImage[123]D(). - * \return error code or GL_NO_ERROR. + * \return GL_TRUE if error, GL_FALSE if no error */ -static GLenum +static GLboolean compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, @@ -4258,13 +4243,12 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, } /* Check for invalid pixel storage modes */ - if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dims, - &ctx->Unpack, - "glCompressedTexSubImage")) { - return GL_FALSE; + if (!_mesa_compressed_pixel_storage_error_check(ctx, dims, + &ctx->Unpack, + "glCompressedTexSubImage")) { + return GL_TRUE; } - expectedSize = compressed_tex_size(width, height, depth, format); if (expectedSize != imageSize) { _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage%uD(size=%d)", diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 52bfa7816..4b27381a0 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -339,12 +339,6 @@ _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); -bool -_mesa_compressed_texture_pixel_storage_error_check(struct gl_context *ctx, - GLint dimensions, - struct gl_pixelstore_attrib *packing, - const char *caller); - /*@}*/ #ifdef __cplusplus diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 30dd0b9b3..e40fb249e 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -1384,7 +1384,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) if (!obj) return; - _mesa_lock_texture(ctx, obj); + _mesa_lock_context_textures(ctx); switch (pname) { case GL_TEXTURE_MAG_FILTER: *params = ENUM_TO_FLOAT(obj->Sampler.MagFilter); @@ -1591,11 +1591,11 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) } /* no error if we get here */ - _mesa_unlock_texture(ctx, obj); + _mesa_unlock_context_textures(ctx); return; invalid_pname: - _mesa_unlock_texture(ctx, obj); + _mesa_unlock_context_textures(ctx); _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", pname); } diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 0e036d9eb..d2aba8ba1 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -68,6 +68,7 @@ #include "texcompress_rgtc.h" #include "texcompress_s3tc.h" #include "texcompress_etc.h" +#include "texcompress_bptc.h" #include "teximage.h" #include "texstore.h" #include "enums.h" @@ -1426,6 +1427,15 @@ texstore_compressed(TEXSTORE_PARAMS) table[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] = _mesa_texstore_etc2_srgb8_punchthrough_alpha1; + table[MESA_FORMAT_BPTC_RGBA_UNORM] = + _mesa_texstore_bptc_rgba_unorm; + table[MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM] = + _mesa_texstore_bptc_rgba_unorm; + table[MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT] = + _mesa_texstore_bptc_rgb_signed_float; + table[MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT] = + _mesa_texstore_bptc_rgb_unsigned_float; + initialized = GL_TRUE; } @@ -1485,6 +1495,12 @@ texstore_swizzle(TEXSTORE_PARAMS) if (!is_array) return GL_FALSE; + if (srcFormat == GL_COLOR_INDEX) + return GL_FALSE; + + if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) + return GL_FALSE; + switch (srcType) { case GL_FLOAT: case GL_UNSIGNED_BYTE: @@ -2175,14 +2191,23 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, } +/** + * Compute compressed_pixelstore parameters for copying compressed + * texture data. + * \param dims number of texture image dimensions: 1, 2 or 3 + * \param texFormat the compressed texture format + * \param width, height, depth size of image to copy + * \param packing pixelstore parameters describing user-space image packing + * \param store returns the compressed_pixelstore parameters + */ void -_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage, - GLsizei width, GLsizei height, GLsizei depth, - const struct gl_pixelstore_attrib *packing, - struct compressed_pixelstore *store) +_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat, + GLsizei width, GLsizei height, + GLsizei depth, + const struct gl_pixelstore_attrib *packing, + struct compressed_pixelstore *store) { GLuint bw, bh; - const mesa_format texFormat = texImage->TexFormat; _mesa_get_format_block_size(texFormat, &bw, &bh); @@ -2252,8 +2277,9 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, return; } - _mesa_compute_compressed_pixelstore(dims, texImage, width, height, depth, - &ctx->Unpack, &store); + _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat, + width, height, depth, + &ctx->Unpack, &store); /* get pointer to src pixels (may be in a pbo which we'll map here) */ data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data, diff --git a/mesalib/src/mesa/main/texstore.h b/mesalib/src/mesa/main/texstore.h index dd1e1d015..4c41d1fcd 100644 --- a/mesalib/src/mesa/main/texstore.h +++ b/mesalib/src/mesa/main/texstore.h @@ -150,10 +150,11 @@ struct compressed_pixelstore { extern void -_mesa_compute_compressed_pixelstore(GLuint dims, struct gl_texture_image *texImage, - GLsizei width, GLsizei height, GLsizei depth, - const struct gl_pixelstore_attrib *packing, - struct compressed_pixelstore *store); +_mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat, + GLsizei width, GLsizei height, + GLsizei depth, + const struct gl_pixelstore_attrib *packing, + struct compressed_pixelstore *store); #endif diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 7e630e65b..4cd2bca01 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -799,9 +799,9 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, for (i = 0; i < elems; i++) { if (basicType == GLSL_TYPE_FLOAT) { - dst[i].i = src[i].f != 0.0f ? 1 : 0; + dst[i].i = src[i].f != 0.0f ? ctx->Const.UniformBooleanTrue : 0; } else { - dst[i].i = src[i].i != 0 ? 1 : 0; + dst[i].i = src[i].i != 0 ? ctx->Const.UniformBooleanTrue : 0; } } } diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index 230fb30cb..5d3cc2a70 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -1553,14 +1553,14 @@ _mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers, */ if (offsets[i] < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(offsets[%u]=%" PRId64 " < 0)", + "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)", i, (int64_t) offsets[i]); continue; } if (strides[i] < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glBindVertexBuffer(strides[%u]=%d < 0)", + "glBindVertexBuffers(strides[%u]=%d < 0)", i, strides[i]); continue; } diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h index f94ebac99..d5d8b363d 100644 --- a/mesalib/src/mesa/main/varray.h +++ b/mesalib/src/mesa/main/varray.h @@ -272,6 +272,10 @@ extern void GLAPIENTRY _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count); extern void GLAPIENTRY +_mesa_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, + GLsizei primcount); + +extern void GLAPIENTRY _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index b3ae3f5e8..126032740 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -124,8 +124,9 @@ create_version_string(struct gl_context *ctx, const char *prefix) * 3.1: select a Core profile with GL version 3.1 * 3.1FC: select a Core+Forward Compatible profile with GL version 3.1 */ -void -_mesa_override_gl_version(struct gl_context *ctx) +bool +_mesa_override_gl_version_contextless(struct gl_constants *consts, + gl_api *apiOut, GLuint *versionOut) { int version; GLboolean fwd_context; @@ -133,15 +134,25 @@ _mesa_override_gl_version(struct gl_context *ctx) get_gl_override(&version, &fwd_context); if (version > 0) { - ctx->Version = version; + *versionOut = version; if (version >= 30 && fwd_context) { - ctx->API = API_OPENGL_CORE; - ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; + *apiOut = API_OPENGL_CORE; + consts->ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; } else if (version >= 31) { - ctx->API = API_OPENGL_CORE; + *apiOut = API_OPENGL_CORE; } else { - ctx->API = API_OPENGL_COMPAT; + *apiOut = API_OPENGL_COMPAT; } + return GL_TRUE; + } + return GL_FALSE; +} + +void +_mesa_override_gl_version(struct gl_context *ctx) +{ + if (_mesa_override_gl_version_contextless(&ctx->Const, &ctx->API, + &ctx->Version)) { create_version_string(ctx, ""); } } @@ -168,7 +179,7 @@ _mesa_get_gl_version_override(void) * MESA_GLSL_VERSION_OVERRIDE are integers, such as "130". */ void -_mesa_override_glsl_version(struct gl_context *ctx) +_mesa_override_glsl_version(struct gl_constants *consts) { const char *env_var = "MESA_GLSL_VERSION_OVERRIDE"; const char *version; @@ -179,7 +190,7 @@ _mesa_override_glsl_version(struct gl_context *ctx) return; } - n = sscanf(version, "%u", &ctx->Const.GLSLVersion); + n = sscanf(version, "%u", &consts->GLSLVersion); if (n != 1) { fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version); return; @@ -189,31 +200,32 @@ _mesa_override_glsl_version(struct gl_context *ctx) /** * Examine enabled GL extensions to determine GL version. */ -static void -compute_version(struct gl_context *ctx) +static GLuint +compute_version(const struct gl_extensions *extensions, + const struct gl_constants *consts, gl_api api) { - GLuint major, minor; + GLuint major, minor, version; - const GLboolean ver_1_3 = (ctx->Extensions.ARB_texture_border_clamp && - ctx->Extensions.ARB_texture_cube_map && - ctx->Extensions.ARB_texture_env_combine && - ctx->Extensions.ARB_texture_env_dot3); + const GLboolean ver_1_3 = (extensions->ARB_texture_border_clamp && + extensions->ARB_texture_cube_map && + extensions->ARB_texture_env_combine && + extensions->ARB_texture_env_dot3); const GLboolean ver_1_4 = (ver_1_3 && - ctx->Extensions.ARB_depth_texture && - ctx->Extensions.ARB_shadow && - ctx->Extensions.ARB_texture_env_crossbar && - ctx->Extensions.EXT_blend_color && - ctx->Extensions.EXT_blend_func_separate && - ctx->Extensions.EXT_blend_minmax && - ctx->Extensions.EXT_point_parameters); + extensions->ARB_depth_texture && + extensions->ARB_shadow && + extensions->ARB_texture_env_crossbar && + extensions->EXT_blend_color && + extensions->EXT_blend_func_separate && + extensions->EXT_blend_minmax && + extensions->EXT_point_parameters); const GLboolean ver_1_5 = (ver_1_4 && - ctx->Extensions.ARB_occlusion_query); + extensions->ARB_occlusion_query); const GLboolean ver_2_0 = (ver_1_5 && - ctx->Extensions.ARB_point_sprite && - ctx->Extensions.ARB_vertex_shader && - ctx->Extensions.ARB_fragment_shader && - ctx->Extensions.ARB_texture_non_power_of_two && - ctx->Extensions.EXT_blend_equation_separate && + extensions->ARB_point_sprite && + extensions->ARB_vertex_shader && + extensions->ARB_fragment_shader && + extensions->ARB_texture_non_power_of_two && + extensions->EXT_blend_equation_separate && /* Technically, 2.0 requires the functionality * of the EXT version. Enable 2.0 if either @@ -221,61 +233,61 @@ compute_version(struct gl_context *ctx) * driver that only exposes the ATI extension * will fallback to software when necessary. */ - (ctx->Extensions.EXT_stencil_two_side - || ctx->Extensions.ATI_separate_stencil)); + (extensions->EXT_stencil_two_side + || extensions->ATI_separate_stencil)); const GLboolean ver_2_1 = (ver_2_0 && - ctx->Extensions.EXT_pixel_buffer_object && - ctx->Extensions.EXT_texture_sRGB); + extensions->EXT_pixel_buffer_object && + extensions->EXT_texture_sRGB); const GLboolean ver_3_0 = (ver_2_1 && - ctx->Const.GLSLVersion >= 130 && - (ctx->Const.MaxSamples >= 4 || ctx->Const.FakeSWMSAA) && - (ctx->API == API_OPENGL_CORE || - ctx->Extensions.ARB_color_buffer_float) && - ctx->Extensions.ARB_depth_buffer_float && - ctx->Extensions.ARB_half_float_vertex && - ctx->Extensions.ARB_map_buffer_range && - ctx->Extensions.ARB_shader_texture_lod && - ctx->Extensions.ARB_texture_float && - ctx->Extensions.ARB_texture_rg && - ctx->Extensions.ARB_texture_compression_rgtc && - ctx->Extensions.EXT_draw_buffers2 && - ctx->Extensions.ARB_framebuffer_object && - ctx->Extensions.EXT_framebuffer_sRGB && - ctx->Extensions.EXT_packed_float && - ctx->Extensions.EXT_texture_array && - ctx->Extensions.EXT_texture_shared_exponent && - ctx->Extensions.EXT_transform_feedback && - ctx->Extensions.NV_conditional_render); + consts->GLSLVersion >= 130 && + (consts->MaxSamples >= 4 || consts->FakeSWMSAA) && + (api == API_OPENGL_CORE || + extensions->ARB_color_buffer_float) && + extensions->ARB_depth_buffer_float && + extensions->ARB_half_float_vertex && + extensions->ARB_map_buffer_range && + extensions->ARB_shader_texture_lod && + extensions->ARB_texture_float && + extensions->ARB_texture_rg && + extensions->ARB_texture_compression_rgtc && + extensions->EXT_draw_buffers2 && + extensions->ARB_framebuffer_object && + extensions->EXT_framebuffer_sRGB && + extensions->EXT_packed_float && + extensions->EXT_texture_array && + extensions->EXT_texture_shared_exponent && + extensions->EXT_transform_feedback && + extensions->NV_conditional_render); const GLboolean ver_3_1 = (ver_3_0 && - ctx->Const.GLSLVersion >= 140 && - ctx->Extensions.ARB_draw_instanced && - ctx->Extensions.ARB_texture_buffer_object && - ctx->Extensions.ARB_uniform_buffer_object && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.NV_primitive_restart && - ctx->Extensions.NV_texture_rectangle && - ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16); + consts->GLSLVersion >= 140 && + extensions->ARB_draw_instanced && + extensions->ARB_texture_buffer_object && + extensions->ARB_uniform_buffer_object && + extensions->EXT_texture_snorm && + extensions->NV_primitive_restart && + extensions->NV_texture_rectangle && + consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16); const GLboolean ver_3_2 = (ver_3_1 && - ctx->Const.GLSLVersion >= 150 && - ctx->Extensions.ARB_depth_clamp && - ctx->Extensions.ARB_draw_elements_base_vertex && - ctx->Extensions.ARB_fragment_coord_conventions && - ctx->Extensions.EXT_provoking_vertex && - ctx->Extensions.ARB_seamless_cube_map && - ctx->Extensions.ARB_sync && - ctx->Extensions.ARB_texture_multisample && - ctx->Extensions.EXT_vertex_array_bgra); + consts->GLSLVersion >= 150 && + extensions->ARB_depth_clamp && + extensions->ARB_draw_elements_base_vertex && + extensions->ARB_fragment_coord_conventions && + extensions->EXT_provoking_vertex && + extensions->ARB_seamless_cube_map && + extensions->ARB_sync && + extensions->ARB_texture_multisample && + extensions->EXT_vertex_array_bgra); const GLboolean ver_3_3 = (ver_3_2 && - ctx->Const.GLSLVersion >= 330 && - ctx->Extensions.ARB_blend_func_extended && - ctx->Extensions.ARB_explicit_attrib_location && - ctx->Extensions.ARB_instanced_arrays && - ctx->Extensions.ARB_occlusion_query2 && - ctx->Extensions.ARB_shader_bit_encoding && - ctx->Extensions.ARB_texture_rgb10_a2ui && - ctx->Extensions.ARB_timer_query && - ctx->Extensions.ARB_vertex_type_2_10_10_10_rev && - ctx->Extensions.EXT_texture_swizzle); + consts->GLSLVersion >= 330 && + extensions->ARB_blend_func_extended && + extensions->ARB_explicit_attrib_location && + extensions->ARB_instanced_arrays && + extensions->ARB_occlusion_query2 && + extensions->ARB_shader_bit_encoding && + extensions->ARB_texture_rgb10_a2ui && + extensions->ARB_timer_query && + extensions->ARB_vertex_type_2_10_10_10_rev && + extensions->EXT_texture_swizzle); /* ARB_sampler_objects is always enabled in mesa */ if (ver_3_3) { @@ -319,74 +331,95 @@ compute_version(struct gl_context *ctx) minor = 2; } - ctx->Version = major * 10 + minor; + version = major * 10 + minor; - create_version_string(ctx, ""); + if (api == API_OPENGL_CORE && version < 31) + return 0; + + return version; } -static void -compute_version_es1(struct gl_context *ctx) +static GLuint +compute_version_es1(const struct gl_extensions *extensions) { /* OpenGL ES 1.0 is derived from OpenGL 1.3 */ - const GLboolean ver_1_0 = (ctx->Extensions.ARB_texture_env_combine && - ctx->Extensions.ARB_texture_env_dot3); + const GLboolean ver_1_0 = (extensions->ARB_texture_env_combine && + extensions->ARB_texture_env_dot3); /* OpenGL ES 1.1 is derived from OpenGL 1.5 */ const GLboolean ver_1_1 = (ver_1_0 && - ctx->Extensions.EXT_point_parameters); + extensions->EXT_point_parameters); if (ver_1_1) { - ctx->Version = 11; + return 11; } else if (ver_1_0) { - ctx->Version = 10; + return 10; } else { - _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support."); + return 0; } - - create_version_string(ctx, "OpenGL ES-CM "); } -static void -compute_version_es2(struct gl_context *ctx) +static GLuint +compute_version_es2(const struct gl_extensions *extensions) { /* OpenGL ES 2.0 is derived from OpenGL 2.0 */ - const GLboolean ver_2_0 = (ctx->Extensions.ARB_texture_cube_map && - ctx->Extensions.EXT_blend_color && - ctx->Extensions.EXT_blend_func_separate && - ctx->Extensions.EXT_blend_minmax && - ctx->Extensions.ARB_vertex_shader && - ctx->Extensions.ARB_fragment_shader && - ctx->Extensions.ARB_texture_non_power_of_two && - ctx->Extensions.EXT_blend_equation_separate); + const GLboolean ver_2_0 = (extensions->ARB_texture_cube_map && + extensions->EXT_blend_color && + extensions->EXT_blend_func_separate && + extensions->EXT_blend_minmax && + extensions->ARB_vertex_shader && + extensions->ARB_fragment_shader && + extensions->ARB_texture_non_power_of_two && + extensions->EXT_blend_equation_separate); /* FINISHME: This list isn't quite right. */ - const GLboolean ver_3_0 = (ctx->Extensions.ARB_half_float_vertex && - ctx->Extensions.ARB_internalformat_query && - ctx->Extensions.ARB_map_buffer_range && - ctx->Extensions.ARB_shader_texture_lod && - ctx->Extensions.ARB_texture_float && - ctx->Extensions.ARB_texture_rg && - ctx->Extensions.ARB_texture_compression_rgtc && - ctx->Extensions.EXT_draw_buffers2 && - /* ctx->Extensions.ARB_framebuffer_object && */ - ctx->Extensions.EXT_framebuffer_sRGB && - ctx->Extensions.EXT_packed_float && - ctx->Extensions.EXT_texture_array && - ctx->Extensions.EXT_texture_shared_exponent && - ctx->Extensions.EXT_transform_feedback && - ctx->Extensions.NV_conditional_render && - ctx->Extensions.ARB_draw_instanced && - ctx->Extensions.ARB_uniform_buffer_object && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.NV_primitive_restart && - ctx->Extensions.OES_depth_texture_cube_map); + const GLboolean ver_3_0 = (extensions->ARB_half_float_vertex && + extensions->ARB_internalformat_query && + extensions->ARB_map_buffer_range && + extensions->ARB_shader_texture_lod && + extensions->ARB_texture_float && + extensions->ARB_texture_rg && + extensions->ARB_texture_compression_rgtc && + extensions->EXT_draw_buffers2 && + /* extensions->ARB_framebuffer_object && */ + extensions->EXT_framebuffer_sRGB && + extensions->EXT_packed_float && + extensions->EXT_texture_array && + extensions->EXT_texture_shared_exponent && + extensions->EXT_transform_feedback && + extensions->NV_conditional_render && + extensions->ARB_draw_instanced && + extensions->ARB_uniform_buffer_object && + extensions->EXT_texture_snorm && + extensions->NV_primitive_restart && + extensions->OES_depth_texture_cube_map); if (ver_3_0) { - ctx->Version = 30; + return 30; } else if (ver_2_0) { - ctx->Version = 20; + return 20; } else { - _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support."); + return 0; } +} - create_version_string(ctx, "OpenGL ES "); +GLuint +_mesa_get_version(const struct gl_extensions *extensions, + struct gl_constants *consts, gl_api api) +{ + switch (api) { + case API_OPENGL_COMPAT: + /* Disable GLSL 1.40 and later for legacy contexts. + * This disallows creation of the GL 3.1 compatibility context. */ + if (consts->GLSLVersion > 130) { + consts->GLSLVersion = 130; + } + /* fall through */ + case API_OPENGL_CORE: + return compute_version(extensions, consts, api); + case API_OPENGLES: + return compute_version_es1(extensions); + case API_OPENGLES2: + return compute_version_es2(extensions); + } + return 0; } /** @@ -400,23 +433,28 @@ _mesa_compute_version(struct gl_context *ctx) if (ctx->Version) return; + ctx->Version = _mesa_get_version(&ctx->Extensions, &ctx->Const, ctx->API); + switch (ctx->API) { case API_OPENGL_COMPAT: - /* Disable GLSL 1.40 and later for legacy contexts. - * This disallows creation of the GL 3.1 compatibility context. */ - if (ctx->Const.GLSLVersion > 130) { - ctx->Const.GLSLVersion = 130; - } - /* fall through */ case API_OPENGL_CORE: - compute_version(ctx); + create_version_string(ctx, ""); break; + case API_OPENGLES: - compute_version_es1(ctx); + if (!ctx->Version) { + _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support."); + return; + } + create_version_string(ctx, "OpenGL ES-CM "); break; + case API_OPENGLES2: - compute_version_es2(ctx); + if (!ctx->Version) { + _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support."); + return; + } + create_version_string(ctx, "OpenGL ES "); break; } - } diff --git a/mesalib/src/mesa/main/version.h b/mesalib/src/mesa/main/version.h index c78f87a2b..450a0e31d 100644 --- a/mesalib/src/mesa/main/version.h +++ b/mesalib/src/mesa/main/version.h @@ -27,18 +27,25 @@ #ifndef VERSION_H #define VERSION_H +#include "mtypes.h" -struct gl_context; +extern GLuint +_mesa_get_version(const struct gl_extensions *extensions, + struct gl_constants *consts, gl_api api); extern void _mesa_compute_version(struct gl_context *ctx); +extern bool +_mesa_override_gl_version_contextless(struct gl_constants *consts, + gl_api *apiOut, GLuint *versionOut); + extern void _mesa_override_gl_version(struct gl_context *ctx); extern void -_mesa_override_glsl_version(struct gl_context *ctx); +_mesa_override_glsl_version(struct gl_constants *consts); extern int _mesa_get_gl_version_override(void); diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index b088160d3..e5844c3c4 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -1459,6 +1459,10 @@ ir_to_mesa_visitor::visit(ir_expression *ir) case ir_unop_interpolate_at_centroid: case ir_binop_interpolate_at_offset: case ir_binop_interpolate_at_sample: + case ir_unop_dFdx_coarse: + case ir_unop_dFdx_fine: + case ir_unop_dFdy_coarse: + case ir_unop_dFdy_fine: assert(!"not supported"); break; @@ -2428,8 +2432,7 @@ add_uniform_to_shader::visit_field(const glsl_type *type, const char *name, } gl_register_file file; - if (type->is_sampler() || - (type->is_array() && type->fields.array->is_sampler())) { + if (type->without_array()->is_sampler()) { file = PROGRAM_SAMPLER; } else { file = PROGRAM_UNIFORM; @@ -2795,7 +2798,7 @@ get_mesa_program(struct gl_context *ctx, GLenum target = _mesa_shader_stage_to_program(shader->Stage); const char *target_string = _mesa_shader_stage_to_string(shader->Stage); struct gl_shader_compiler_options *options = - &ctx->ShaderCompilerOptions[shader->Stage]; + &ctx->Const.ShaderCompilerOptions[shader->Stage]; validate_ir_tree(shader->ir); @@ -2980,7 +2983,7 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) bool progress; exec_list *ir = prog->_LinkedShaders[i]->ir; const struct gl_shader_compiler_options *options = - &ctx->ShaderCompilerOptions[prog->_LinkedShaders[i]->Stage]; + &ctx->Const.ShaderCompilerOptions[prog->_LinkedShaders[i]->Stage]; do { progress = false; diff --git a/mesalib/src/mesa/program/programopt.c b/mesalib/src/mesa/program/programopt.c index 92a8831d2..b654b1db6 100644 --- a/mesalib/src/mesa/program/programopt.c +++ b/mesalib/src/mesa/program/programopt.c @@ -218,7 +218,7 @@ _mesa_insert_mvp_mad_code(struct gl_context *ctx, struct gl_vertex_program *vpro void _mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog) { - if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS) + if (ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS) _mesa_insert_mvp_dp4_code( ctx, vprog ); else _mesa_insert_mvp_mad_code( ctx, vprog ); diff --git a/mesalib/src/mesa/program/register_allocate.c b/mesalib/src/mesa/program/register_allocate.c index 549154e8a..db2be5dfa 100644 --- a/mesalib/src/mesa/program/register_allocate.c +++ b/mesalib/src/mesa/program/register_allocate.c @@ -146,6 +146,12 @@ struct ra_node { */ bool in_stack; + /** + * The q total, as defined in the Runeson/Nyström paper, for all the + * interfering nodes not in the stack. + */ + unsigned int q_total; + /* For an implementation that needs register spilling, this is the * approximate cost of spilling this node. */ @@ -162,16 +168,6 @@ struct ra_graph { unsigned int *stack; unsigned int stack_count; - - /** - * Tracks the start of the set of optimistically-colored registers in the - * stack. - * - * Along with any registers not in the stack (if one called ra_simplify() - * and didn't do optimistic coloring), these need to be considered for - * spilling. - */ - unsigned int stack_optimistic_start; }; /** @@ -354,6 +350,12 @@ ra_add_node_adjacency(struct ra_graph *g, unsigned int n1, unsigned int n2) { BITSET_SET(g->nodes[n1].adjacency, n2); + if (n1 != n2) { + int n1_class = g->nodes[n1].class; + int n2_class = g->nodes[n2].class; + g->nodes[n1].q_total += g->regs->classes[n1_class]->q[n2_class]; + } + if (g->nodes[n1].adjacency_count >= g->nodes[n1].adjacency_list_size) { g->nodes[n1].adjacency_list_size *= 2; @@ -387,6 +389,7 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count) g->nodes[i].adjacency_list = ralloc_array(g, unsigned int, g->nodes[i].adjacency_list_size); g->nodes[i].adjacency_count = 0; + g->nodes[i].q_total = 0; ra_add_node_adjacency(g, i, i); g->nodes[i].reg = NO_REG; @@ -415,20 +418,25 @@ ra_add_node_interference(struct ra_graph *g, static bool pq_test(struct ra_graph *g, unsigned int n) { - unsigned int j; - unsigned int q = 0; int n_class = g->nodes[n].class; - for (j = 0; j < g->nodes[n].adjacency_count; j++) { - unsigned int n2 = g->nodes[n].adjacency_list[j]; + return g->nodes[n].q_total < g->regs->classes[n_class]->p; +} + +static void +decrement_q(struct ra_graph *g, unsigned int n) +{ + unsigned int i; + int n_class = g->nodes[n].class; + + for (i = 0; i < g->nodes[n].adjacency_count; i++) { + unsigned int n2 = g->nodes[n].adjacency_list[i]; unsigned int n2_class = g->nodes[n2].class; if (n != n2 && !g->nodes[n2].in_stack) { - q += g->regs->classes[n_class]->q[n2_class]; + g->nodes[n2].q_total -= g->regs->classes[n2_class]->q[n_class]; } } - - return q < g->regs->classes[n_class]->p; } /** @@ -436,17 +444,21 @@ pq_test(struct ra_graph *g, unsigned int n) * trivially-colorable nodes into a stack of nodes to be colored, * removing them from the graph, and rinsing and repeating. * - * Returns true if all nodes were removed from the graph. false - * means that either spilling will be required, or optimistic coloring - * should be applied. + * If we encounter a case where we can't push any nodes on the stack, then + * we optimistically choose a node and push it on the stack. We heuristically + * push the node with the lowest total q value, since it has the fewest + * neighbors and therefore is most likely to be allocated. */ -bool +static void ra_simplify(struct ra_graph *g) { bool progress = true; int i; while (progress) { + unsigned int best_optimistic_node = ~0; + unsigned int lowest_q_total = ~0; + progress = false; for (i = g->count - 1; i >= 0; i--) { @@ -454,20 +466,28 @@ ra_simplify(struct ra_graph *g) continue; if (pq_test(g, i)) { + decrement_q(g, i); g->stack[g->stack_count] = i; g->stack_count++; g->nodes[i].in_stack = true; progress = true; + } else { + unsigned int new_q_total = g->nodes[i].q_total; + if (new_q_total < lowest_q_total) { + best_optimistic_node = i; + lowest_q_total = new_q_total; + } } } - } - for (i = 0; i < g->count; i++) { - if (!g->nodes[i].in_stack && g->nodes[i].reg == -1) - return false; + if (!progress && best_optimistic_node != ~0) { + decrement_q(g, best_optimistic_node); + g->stack[g->stack_count] = best_optimistic_node; + g->stack_count++; + g->nodes[best_optimistic_node].in_stack = true; + progress = true; + } } - - return true; } /** @@ -477,7 +497,7 @@ ra_simplify(struct ra_graph *g) * If all nodes were trivially colorable, then this must succeed. If * not (optimistic coloring), then it may return false; */ -bool +static bool ra_select(struct ra_graph *g) { int i; @@ -509,11 +529,16 @@ ra_select(struct ra_graph *g) if (i == g->nodes[n].adjacency_count) break; } + + /* set this to false even if we return here so that + * ra_get_best_spill_node() considers this node later. + */ + g->nodes[n].in_stack = false; + if (ri == g->regs->count) return false; g->nodes[n].reg = r; - g->nodes[n].in_stack = false; g->stack_count--; if (g->regs->round_robin) @@ -523,35 +548,10 @@ ra_select(struct ra_graph *g) return true; } -/** - * Optimistic register coloring: Just push the remaining nodes - * on the stack. They'll be colored first in ra_select(), and - * if they succeed then the locally-colorable nodes are still - * locally-colorable and the rest of the register allocation - * will succeed. - */ -void -ra_optimistic_color(struct ra_graph *g) -{ - unsigned int i; - - g->stack_optimistic_start = g->stack_count; - for (i = 0; i < g->count; i++) { - if (g->nodes[i].in_stack || g->nodes[i].reg != NO_REG) - continue; - - g->stack[g->stack_count] = i; - g->stack_count++; - g->nodes[i].in_stack = true; - } -} - bool -ra_allocate_no_spills(struct ra_graph *g) +ra_allocate(struct ra_graph *g) { - if (!ra_simplify(g)) { - ra_optimistic_color(g); - } + ra_simplify(g); return ra_select(g); } @@ -614,15 +614,12 @@ ra_get_best_spill_node(struct ra_graph *g) { unsigned int best_node = -1; float best_benefit = 0.0; - unsigned int n, i; + unsigned int n; - /* For any registers not in the stack to be colored, consider them for - * spilling. This will mostly collect nodes that were being optimistally - * colored as part of ra_allocate_no_spills() if we didn't successfully - * optimistically color. - * - * It also includes nodes not trivially colorable by ra_simplify() if it - * was used directly instead of as part of ra_allocate_no_spills(). + /* Consider any nodes that we colored successfully or the node we failed to + * color for spilling. When we failed to color a node in ra_select(), we + * only considered these nodes, so spilling any other ones would not result + * in us making progress. */ for (n = 0; n < g->count; n++) { float cost = g->nodes[n].spill_cost; @@ -642,26 +639,6 @@ ra_get_best_spill_node(struct ra_graph *g) } } - /* Also consider spilling any nodes that were set up to be optimistically - * colored that we couldn't manage to color in ra_select(). - */ - for (i = g->stack_optimistic_start; i < g->stack_count; i++) { - float cost, benefit; - - n = g->stack[i]; - cost = g->nodes[n].spill_cost; - - if (cost <= 0.0) - continue; - - benefit = ra_get_spill_benefit(g, n); - - if (benefit / cost > best_benefit) { - best_benefit = benefit / cost; - best_node = n; - } - } - return best_node; } diff --git a/mesalib/src/mesa/program/register_allocate.h b/mesalib/src/mesa/program/register_allocate.h index 337dcf709..bfc9190dc 100644 --- a/mesalib/src/mesa/program/register_allocate.h +++ b/mesalib/src/mesa/program/register_allocate.h @@ -66,10 +66,7 @@ void ra_add_node_interference(struct ra_graph *g, /** @} */ /** @{ Graph-coloring register allocation */ -bool ra_simplify(struct ra_graph *g); -void ra_optimistic_color(struct ra_graph *g); -bool ra_select(struct ra_graph *g); -bool ra_allocate_no_spills(struct ra_graph *g); +bool ra_allocate(struct ra_graph *g); unsigned int ra_get_node_reg(struct ra_graph *g, unsigned int n); void ra_set_node_reg(struct ra_graph * g, unsigned int n, unsigned int reg); diff --git a/mesalib/src/mesa/program/sampler.cpp b/mesalib/src/mesa/program/sampler.cpp index e6532be84..29a540871 100644 --- a/mesalib/src/mesa/program/sampler.cpp +++ b/mesalib/src/mesa/program/sampler.cpp @@ -134,3 +134,14 @@ _mesa_get_sampler_uniform_value(class ir_dereference *sampler, return shader_program->UniformStorage[location].sampler[shader].index + getname.offset; } + + +extern "C" class ir_rvalue * +_mesa_get_sampler_array_nonconst_index(class ir_dereference *sampler) +{ + ir_dereference_array *deref_arr = sampler->as_dereference_array(); + if (!deref_arr || deref_arr->array_index->as_constant()) + return NULL; + + return deref_arr->array_index; +} diff --git a/mesalib/src/mesa/program/sampler.h b/mesalib/src/mesa/program/sampler.h index 22467e990..8b7c3b63e 100644 --- a/mesalib/src/mesa/program/sampler.h +++ b/mesalib/src/mesa/program/sampler.h @@ -27,3 +27,6 @@ int _mesa_get_sampler_uniform_value(class ir_dereference *sampler, struct gl_shader_program *shader_program, const struct gl_program *prog); + +class ir_rvalue * +_mesa_get_sampler_array_nonconst_index(class ir_dereference *sampler); diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c index 2e10bc3e2..03d05932a 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_texture.c +++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c @@ -338,7 +338,7 @@ update_single_texture(struct st_context *st, /* Determine the format of the texture sampler view */ if (texObj->Target == GL_TEXTURE_BUFFER) { view_format = - st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat); + st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat); } else { view_format = diff --git a/mesalib/src/mesa/state_tracker/st_cb_condrender.c b/mesalib/src/mesa/state_tracker/st_cb_condrender.c index 8776985f9..f02472aec 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_condrender.c +++ b/mesalib/src/mesa/state_tracker/st_cb_condrender.c @@ -55,6 +55,8 @@ st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q, struct st_query_object *stq = st_query_object(q); struct st_context *st = st_context(ctx); uint m; + /* Don't invert the condition for rendering by default */ + boolean inverted = FALSE; st_flush_bitmap_cache(st); @@ -71,12 +73,28 @@ st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q, case GL_QUERY_BY_REGION_NO_WAIT: m = PIPE_RENDER_COND_BY_REGION_NO_WAIT; break; + case GL_QUERY_WAIT_INVERTED: + m = PIPE_RENDER_COND_WAIT; + inverted = TRUE; + break; + case GL_QUERY_NO_WAIT_INVERTED: + m = PIPE_RENDER_COND_NO_WAIT; + inverted = TRUE; + break; + case GL_QUERY_BY_REGION_WAIT_INVERTED: + m = PIPE_RENDER_COND_BY_REGION_WAIT; + inverted = TRUE; + break; + case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: + m = PIPE_RENDER_COND_BY_REGION_NO_WAIT; + inverted = TRUE; + break; default: assert(0 && "bad mode in st_BeginConditionalRender"); m = PIPE_RENDER_COND_WAIT; } - cso_set_render_condition(st->cso_context, stq->pq, FALSE, m); + cso_set_render_condition(st->cso_context, stq->pq, inverted, m); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index d13a17f50..5ae092b94 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -491,7 +491,7 @@ make_texture(struct st_context *st, /* Choose a pixel format for the temp texture which will hold the * image to draw. */ - pipeFormat = st_choose_matching_format(pipe->screen, PIPE_BIND_SAMPLER_VIEW, + pipeFormat = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW, format, type, unpack->SwapBytes); if (pipeFormat == PIPE_FORMAT_NONE) { diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index ce8d91514..7cfd3dade 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -588,7 +588,7 @@ st_validate_attachment(struct gl_context *ctx, if (!ctx->Extensions.EXT_framebuffer_sRGB && _mesa_get_format_color_encoding(texFormat) == GL_SRGB) { const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat); - format = st_mesa_format_to_pipe_format(linearFormat); + format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat); } valid = screen->is_format_supported(screen, format, diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index 3f7bbd973..d95a608d3 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -143,7 +143,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, /* Choose the destination format by finding the best match * for the format+type combo. */ - dst_format = st_choose_matching_format(screen, bind, format, type, + dst_format = st_choose_matching_format(st, bind, format, type, pack->SwapBytes); if (dst_format == PIPE_FORMAT_NONE) { goto fallback; diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index c4b2107ba..ad14bd939 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -37,6 +37,7 @@ #include "main/pbo.h" #include "main/pixeltransfer.h" #include "main/texcompress.h" +#include "main/texcompress_etc.h" #include "main/texgetimage.h" #include "main/teximage.h" #include "main/texobj.h" @@ -207,8 +208,32 @@ st_MapTextureImage(struct gl_context *ctx, map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1, &transfer); if (map) { - *mapOut = map; - *rowStrideOut = transfer->stride; + if (_mesa_is_format_etc2(texImage->TexFormat) || + (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) { + /* ETC isn't supported by gallium and it's represented + * by uncompressed formats. Only write transfers with precompressed + * data are supported by ES3, which makes this really simple. + * + * Just create a temporary storage where the ETC texture will + * be stored. It will be decompressed in the Unmap function. + */ + unsigned z = transfer->box.z; + struct st_texture_image_transfer *itransfer = &stImage->transfer[z]; + + itransfer->temp_data = + malloc(_mesa_format_image_size(texImage->TexFormat, w, h, 1)); + itransfer->temp_stride = + _mesa_format_row_stride(texImage->TexFormat, w); + itransfer->map = map; + + *mapOut = itransfer->temp_data; + *rowStrideOut = itransfer->temp_stride; + } + else { + /* supported mapping */ + *mapOut = map; + *rowStrideOut = transfer->stride; + } } else { *mapOut = NULL; @@ -225,6 +250,35 @@ st_UnmapTextureImage(struct gl_context *ctx, { struct st_context *st = st_context(ctx); struct st_texture_image *stImage = st_texture_image(texImage); + + if (_mesa_is_format_etc2(texImage->TexFormat) || + (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1)) { + /* Decompress the ETC texture to the mapped one. */ + unsigned z = slice + stImage->base.Face; + struct st_texture_image_transfer *itransfer = &stImage->transfer[z]; + struct pipe_transfer *transfer = itransfer->transfer; + + assert(z == transfer->box.z); + + if (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8) { + _mesa_etc1_unpack_rgba8888(itransfer->map, transfer->stride, + itransfer->temp_data, + itransfer->temp_stride, + transfer->box.width, transfer->box.height); + } + else { + _mesa_unpack_etc2_format(itransfer->map, transfer->stride, + itransfer->temp_data, itransfer->temp_stride, + transfer->box.width, transfer->box.height, + texImage->TexFormat); + } + + free(itransfer->temp_data); + itransfer->temp_data = NULL; + itransfer->temp_stride = 0; + itransfer->map = 0; + } + st_texture_image_unmap(st, stImage, slice); } @@ -398,7 +452,7 @@ guess_and_alloc_texture(struct st_context *st, stObj->height0 = height; stObj->depth0 = depth; - fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat); + fmt = st_mesa_format_to_pipe_format(st, stImage->base.TexFormat); bindings = default_bindings(st, fmt); @@ -449,7 +503,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, /* Look if the parent texture object has space for this image */ if (stObj->pt && level <= stObj->pt->last_level && - st_texture_match_image(stObj->pt, texImage)) { + st_texture_match_image(st, stObj->pt, texImage)) { /* this image will fit in the existing texture object's memory */ pipe_resource_reference(&stImage->pt, stObj->pt); return GL_TRUE; @@ -472,7 +526,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, } if (stObj->pt && - st_texture_match_image(stObj->pt, texImage)) { + st_texture_match_image(st, stObj->pt, texImage)) { /* The image will live in the object's mipmap memory */ pipe_resource_reference(&stImage->pt, stObj->pt); assert(stImage->pt); @@ -486,7 +540,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, * level. */ enum pipe_format format = - st_mesa_format_to_pipe_format(texImage->TexFormat); + st_mesa_format_to_pipe_format(st, texImage->TexFormat); GLuint bindings = default_bindings(st, format); GLuint ptWidth, ptHeight, ptDepth, ptLayers; @@ -613,6 +667,9 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, unsigned bind; GLubyte *map; + assert(!_mesa_is_format_etc2(texImage->TexFormat) && + texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); + if (!st->prefer_blit_based_texture_transfer) { goto fallback; } @@ -660,7 +717,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, } /* Choose the source format. */ - src_format = st_choose_matching_format(screen, PIPE_BIND_SAMPLER_VIEW, + src_format = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW, format, type, unpack->SwapBytes); if (!src_format) { goto fallback; @@ -872,6 +929,9 @@ st_GetTexImage(struct gl_context * ctx, ubyte *map = NULL; boolean done = FALSE; + assert(!_mesa_is_format_etc2(texImage->TexFormat) && + texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); + if (!st->prefer_blit_based_texture_transfer && !_mesa_is_format_compressed(texImage->TexFormat)) { /* Try to avoid the fallback if we're doing texture decompression here */ @@ -934,7 +994,7 @@ st_GetTexImage(struct gl_context * ctx, /* Choose the destination format by finding the best match * for the format+type combo. */ - dst_format = st_choose_matching_format(screen, bind, format, type, + dst_format = st_choose_matching_format(st, bind, format, type, ctx->Pack.SwapBytes); if (dst_format == PIPE_FORMAT_NONE) { @@ -956,6 +1016,7 @@ st_GetTexImage(struct gl_context * ctx, case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_RGTC2_UNORM: case PIPE_FORMAT_ETC1_RGB8: + case PIPE_FORMAT_BPTC_RGBA_UNORM: dst_glformat = GL_RGBA8; break; case PIPE_FORMAT_RGTC1_SNORM: @@ -964,7 +1025,12 @@ st_GetTexImage(struct gl_context * ctx, goto fallback; dst_glformat = GL_RGBA8_SNORM; break; - /* TODO: for BPTC_*FLOAT, set RGBA32F and check for ARB_texture_float */ + case PIPE_FORMAT_BPTC_RGB_FLOAT: + case PIPE_FORMAT_BPTC_RGB_UFLOAT: + if (!ctx->Extensions.ARB_texture_float) + goto fallback; + dst_glformat = GL_RGBA32F; + break; default: assert(0); goto fallback; @@ -1308,6 +1374,9 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, unsigned bind; GLint srcY0, srcY1; + assert(!_mesa_is_format_etc2(texImage->TexFormat) && + texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); + if (!strb || !strb->surface || !stImage->pt) { debug_printf("%s: null strb or stImage\n", __FUNCTION__); return; @@ -1531,7 +1600,8 @@ st_finalize_texture(struct gl_context *ctx, } /* Find gallium format for the Mesa texture */ - firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); + firstImageFormat = + st_mesa_format_to_pipe_format(st, firstImage->base.TexFormat); /* Find size of level=0 Gallium mipmap image, plus number of texture layers */ { @@ -1649,7 +1719,7 @@ st_AllocTextureStorage(struct gl_context *ctx, stObj->depth0 = depth; stObj->lastLevel = levels - 1; - fmt = st_mesa_format_to_pipe_format(texImage->TexFormat); + fmt = st_mesa_format_to_pipe_format(st, texImage->TexFormat); bindings = default_bindings(st, fmt); @@ -1728,7 +1798,7 @@ st_TestProxyTexImage(struct gl_context *ctx, GLenum target, memset(&pt, 0, sizeof(pt)); pt.target = gl_target_to_pipe(target); - pt.format = st_mesa_format_to_pipe_format(format); + pt.format = st_mesa_format_to_pipe_format(st, format); st_gl_texture_dims_to_pipe_dims(target, width, height, depth, diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index c805a094b..09b615465 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -189,6 +189,9 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, st->has_stencil_export = screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT); st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3); + st->has_etc1 = screen->is_format_supported(screen, PIPE_FORMAT_ETC1_RGB8, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW); st->prefer_blit_based_texture_transfer = screen->get_param(screen, PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER); @@ -198,10 +201,40 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 | PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600)); + st->has_time_elapsed = + screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED); /* GL limits and extensions */ - st_init_limits(st); - st_init_extensions(st); + st_init_limits(st->pipe->screen, &ctx->Const, &ctx->Extensions); + st_init_extensions(st->pipe->screen, ctx->API, &ctx->Const, + &ctx->Extensions, &st->options, ctx->Mesa_DXTn); + + /* Enable shader-based fallbacks for ARB_color_buffer_float if needed. */ + if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { + if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) { + st->clamp_vert_color_in_shader = GL_TRUE; + } + + if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) { + st->clamp_frag_color_in_shader = GL_TRUE; + } + + /* For drivers which cannot do color clamping, it's better to just + * disable ARB_color_buffer_float in the core profile, because + * the clamping is deprecated there anyway. */ + if (ctx->API == API_OPENGL_CORE && + (st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) { + st->clamp_vert_color_in_shader = GL_FALSE; + st->clamp_frag_color_in_shader = GL_FALSE; + ctx->Extensions.ARB_color_buffer_float = GL_FALSE; + } + } + + /* called after _mesa_create_context/_mesa_init_point, fix default user + * settable max point size up + */ + st->ctx->Point.MaxSize = MAX2(ctx->Const.MaxPointSize, + ctx->Const.MaxPointSizeAA); _mesa_compute_version(ctx); @@ -241,7 +274,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, * driver prefers DP4 or MUL/MAD for vertex transformation. */ if (debug_get_option_mesa_mvp_dp4()) - ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = GL_TRUE; + ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = GL_TRUE; return st_create_context_priv(ctx, pipe, options); } diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 361a24b1d..6d572bd49 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -86,6 +86,7 @@ struct st_context boolean has_stencil_export; /**< can do shader stencil export? */ boolean has_time_elapsed; boolean has_shader_model3; + boolean has_etc1; boolean prefer_blit_based_texture_transfer; boolean needs_texcoord_semantic; diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 7ac484056..4110eb5dd 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -70,10 +70,9 @@ static int _clamp(int a, int min, int max) * Query driver to get implementation limits. * Note that we have to limit/clamp against Mesa's internal limits too. */ -void st_init_limits(struct st_context *st) +void st_init_limits(struct pipe_screen *screen, + struct gl_constants *c, struct gl_extensions *extensions) { - struct pipe_screen *screen = st->pipe->screen; - struct gl_constants *c = &st->ctx->Const; unsigned sh; boolean can_ubo = TRUE; @@ -124,10 +123,7 @@ void st_init_limits(struct st_context *st) c->MaxPointSizeAA = _maxf(1.0f, screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH_AA)); - /* called after _mesa_create_context/_mesa_init_point, fix default user - * settable max point size up - */ - st->ctx->Point.MaxSize = MAX2(c->MaxPointSize, c->MaxPointSizeAA); + /* these are not queryable. Note that GL basically mandates a 1.0 minimum * for non-aa sizes, but we can go down to 0.0 for aa points. */ @@ -158,15 +154,15 @@ void st_init_limits(struct st_context *st) switch (sh) { case PIPE_SHADER_FRAGMENT: pc = &c->Program[MESA_SHADER_FRAGMENT]; - options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; + options = &c->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; break; case PIPE_SHADER_VERTEX: pc = &c->Program[MESA_SHADER_VERTEX]; - options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX]; + options = &c->ShaderCompilerOptions[MESA_SHADER_VERTEX]; break; case PIPE_SHADER_GEOMETRY: pc = &c->Program[MESA_SHADER_GEOMETRY]; - options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_GEOMETRY]; + options = &c->ShaderCompilerOptions[MESA_SHADER_GEOMETRY]; break; default: /* compute shader, etc. */ @@ -191,8 +187,7 @@ void st_init_limits(struct st_context *st) pc->MaxTemps = pc->MaxNativeTemps = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_TEMPS); pc->MaxAddressRegs = pc->MaxNativeAddressRegs = - _min(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_ADDRS), - MAX_PROGRAM_ADDRESS_REGS); + sh == PIPE_SHADER_VERTEX ? 1 : 0; pc->MaxParameters = pc->MaxNativeParameters = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / sizeof(float[4]); @@ -300,7 +295,7 @@ void st_init_limits(struct st_context *st) screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS); if (can_ubo) { - st->ctx->Extensions.ARB_uniform_buffer_object = GL_TRUE; + extensions->ARB_uniform_buffer_object = GL_TRUE; c->UniformBufferOffsetAlignment = screen->get_param(screen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT); c->MaxCombinedUniformBlocks = c->MaxUniformBufferBindings = @@ -340,14 +335,15 @@ struct st_extension_format_mapping { * * target and bind_flags are passed to is_format_supported. */ -static void init_format_extensions(struct st_context *st, - const struct st_extension_format_mapping *mapping, - unsigned num_mappings, - enum pipe_texture_target target, - unsigned bind_flags) +static void +init_format_extensions(struct pipe_screen *screen, + struct gl_extensions *extensions, + const struct st_extension_format_mapping *mapping, + unsigned num_mappings, + enum pipe_texture_target target, + unsigned bind_flags) { - struct pipe_screen *screen = st->pipe->screen; - GLboolean *extensions = (GLboolean *) &st->ctx->Extensions; + GLboolean *extension_table = (GLboolean *) extensions; unsigned i; int j; int num_formats = Elements(mapping->format); @@ -371,10 +367,36 @@ static void init_format_extensions(struct st_context *st, /* Enable all extensions in the list. */ for (j = 0; j < num_ext && mapping[i].extension_offset[j]; j++) - extensions[mapping[i].extension_offset[j]] = GL_TRUE; + extension_table[mapping[i].extension_offset[j]] = GL_TRUE; } } + +/** + * Given a list of formats and bind flags, return the maximum number + * of samples supported by any of those formats. + */ +static unsigned +get_max_samples_for_formats(struct pipe_screen *screen, + unsigned num_formats, + enum pipe_format *formats, + unsigned max_samples, + unsigned bind) +{ + unsigned i, f; + + for (i = max_samples; i > 0; --i) { + for (f = 0; f < num_formats; f++) { + if (screen->is_format_supported(screen, formats[f], + PIPE_TEXTURE_2D, i, bind)) { + return i; + } + } + } + return 0; +} + + /** * Use pipe_screen::get_param() to query PIPE_CAP_ values to determine * which GL extensions are supported. @@ -382,12 +404,15 @@ static void init_format_extensions(struct st_context *st, * features or can be built on top of other gallium features. * Some fine tuning may still be needed. */ -void st_init_extensions(struct st_context *st) +void st_init_extensions(struct pipe_screen *screen, + gl_api api, + struct gl_constants *consts, + struct gl_extensions *extensions, + struct st_config_options *options, + boolean has_lib_dxtc) { - struct pipe_screen *screen = st->pipe->screen; - struct gl_context *ctx = st->ctx; int i, glsl_feature_level; - GLboolean *extensions = (GLboolean *) &ctx->Extensions; + GLboolean *extension_table = (GLboolean *) extensions; static const struct st_extension_cap_mapping cap_mapping[] = { { o(ARB_base_instance), PIPE_CAP_START_INSTANCE }, @@ -433,7 +458,9 @@ void st_init_extensions(struct st_context *st) { o(ARB_texture_multisample), PIPE_CAP_TEXTURE_MULTISAMPLE }, { o(ARB_texture_query_lod), PIPE_CAP_TEXTURE_QUERY_LOD }, { o(ARB_sample_shading), PIPE_CAP_SAMPLE_SHADING }, - { o(ARB_draw_indirect), PIPE_CAP_DRAW_INDIRECT } + { o(ARB_draw_indirect), PIPE_CAP_DRAW_INDIRECT }, + { o(ARB_derivative_control), PIPE_CAP_TGSI_FS_FINE_DERIVATIVE }, + { o(ARB_conditional_render_inverted), PIPE_CAP_CONDITIONAL_RENDER_INVERTED }, }; /* Required: render target and sampler support */ @@ -492,6 +519,12 @@ void st_init_extensions(struct st_context *st) PIPE_FORMAT_DXT3_RGBA, PIPE_FORMAT_DXT5_RGBA } }, + { { o(ARB_texture_compression_bptc) }, + { PIPE_FORMAT_BPTC_RGBA_UNORM, + PIPE_FORMAT_BPTC_SRGBA, + PIPE_FORMAT_BPTC_RGB_FLOAT, + PIPE_FORMAT_BPTC_RGB_UFLOAT } }, + { { o(EXT_texture_shared_exponent) }, { PIPE_FORMAT_R9G9B9E5_FLOAT } }, @@ -513,7 +546,9 @@ void st_init_extensions(struct st_context *st) GL_TRUE }, /* at least one format must be supported */ { { o(OES_compressed_ETC1_RGB8_texture) }, - { PIPE_FORMAT_ETC1_RGB8 } }, + { PIPE_FORMAT_ETC1_RGB8, + PIPE_FORMAT_R8G8B8A8_UNORM }, + GL_TRUE }, /* at least one format must be supported */ { { o(ARB_stencil_texturing) }, { PIPE_FORMAT_X24S8_UINT, @@ -547,256 +582,248 @@ void st_init_extensions(struct st_context *st) /* * Extensions that are supported by all Gallium drivers: */ - ctx->Extensions.ARB_ES2_compatibility = GL_TRUE; - ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE; - ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE; - ctx->Extensions.ARB_explicit_uniform_location = GL_TRUE; - ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; - ctx->Extensions.ARB_fragment_program = GL_TRUE; - ctx->Extensions.ARB_fragment_shader = GL_TRUE; - ctx->Extensions.ARB_half_float_vertex = GL_TRUE; - ctx->Extensions.ARB_internalformat_query = GL_TRUE; - ctx->Extensions.ARB_map_buffer_range = GL_TRUE; - ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */ - ctx->Extensions.ARB_texture_cube_map = GL_TRUE; - ctx->Extensions.ARB_texture_env_combine = GL_TRUE; - ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; - ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE; - ctx->Extensions.ARB_vertex_program = GL_TRUE; - ctx->Extensions.ARB_vertex_shader = GL_TRUE; - - ctx->Extensions.EXT_blend_color = GL_TRUE; - ctx->Extensions.EXT_blend_func_separate = GL_TRUE; - ctx->Extensions.EXT_blend_minmax = GL_TRUE; - ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE; - ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE; - ctx->Extensions.EXT_point_parameters = GL_TRUE; - ctx->Extensions.EXT_provoking_vertex = GL_TRUE; - - ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; - ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; - - ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE; - - ctx->Extensions.MESA_pack_invert = GL_TRUE; - - ctx->Extensions.NV_fog_distance = GL_TRUE; - ctx->Extensions.NV_texture_env_combine4 = GL_TRUE; - ctx->Extensions.NV_texture_rectangle = GL_TRUE; - ctx->Extensions.NV_vdpau_interop = GL_TRUE; - - ctx->Extensions.OES_EGL_image = GL_TRUE; - ctx->Extensions.OES_EGL_image_external = GL_TRUE; - ctx->Extensions.OES_draw_texture = GL_TRUE; + extensions->ARB_ES2_compatibility = GL_TRUE; + extensions->ARB_draw_elements_base_vertex = GL_TRUE; + extensions->ARB_explicit_attrib_location = GL_TRUE; + extensions->ARB_explicit_uniform_location = GL_TRUE; + extensions->ARB_fragment_coord_conventions = GL_TRUE; + extensions->ARB_fragment_program = GL_TRUE; + extensions->ARB_fragment_shader = GL_TRUE; + extensions->ARB_half_float_vertex = GL_TRUE; + extensions->ARB_internalformat_query = GL_TRUE; + extensions->ARB_map_buffer_range = GL_TRUE; + extensions->ARB_texture_border_clamp = GL_TRUE; /* XXX temp */ + extensions->ARB_texture_cube_map = GL_TRUE; + extensions->ARB_texture_env_combine = GL_TRUE; + extensions->ARB_texture_env_crossbar = GL_TRUE; + extensions->ARB_texture_env_dot3 = GL_TRUE; + extensions->ARB_vertex_program = GL_TRUE; + extensions->ARB_vertex_shader = GL_TRUE; + + extensions->EXT_blend_color = GL_TRUE; + extensions->EXT_blend_func_separate = GL_TRUE; + extensions->EXT_blend_minmax = GL_TRUE; + extensions->EXT_gpu_program_parameters = GL_TRUE; + extensions->EXT_pixel_buffer_object = GL_TRUE; + extensions->EXT_point_parameters = GL_TRUE; + extensions->EXT_provoking_vertex = GL_TRUE; + + extensions->EXT_texture_env_dot3 = GL_TRUE; + extensions->EXT_vertex_array_bgra = GL_TRUE; + + extensions->ATI_texture_env_combine3 = GL_TRUE; + + extensions->MESA_pack_invert = GL_TRUE; + + extensions->NV_fog_distance = GL_TRUE; + extensions->NV_texture_env_combine4 = GL_TRUE; + extensions->NV_texture_rectangle = GL_TRUE; + extensions->NV_vdpau_interop = GL_TRUE; + + extensions->OES_EGL_image = GL_TRUE; + extensions->OES_EGL_image_external = GL_TRUE; + extensions->OES_draw_texture = GL_TRUE; /* Expose the extensions which directly correspond to gallium caps. */ for (i = 0; i < Elements(cap_mapping); i++) { if (screen->get_param(screen, cap_mapping[i].cap)) { - extensions[cap_mapping[i].extension_offset] = GL_TRUE; + extension_table[cap_mapping[i].extension_offset] = GL_TRUE; } } /* Expose the extensions which directly correspond to gallium formats. */ - init_format_extensions(st, rendertarget_mapping, + init_format_extensions(screen, extensions, rendertarget_mapping, Elements(rendertarget_mapping), PIPE_TEXTURE_2D, PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW); - init_format_extensions(st, depthstencil_mapping, + init_format_extensions(screen, extensions, depthstencil_mapping, Elements(depthstencil_mapping), PIPE_TEXTURE_2D, PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SAMPLER_VIEW); - init_format_extensions(st, texture_mapping, Elements(texture_mapping), - PIPE_TEXTURE_2D, PIPE_BIND_SAMPLER_VIEW); - init_format_extensions(st, vertex_mapping, Elements(vertex_mapping), - PIPE_BUFFER, PIPE_BIND_VERTEX_BUFFER); + init_format_extensions(screen, extensions, texture_mapping, + Elements(texture_mapping), PIPE_TEXTURE_2D, + PIPE_BIND_SAMPLER_VIEW); + init_format_extensions(screen, extensions, vertex_mapping, + Elements(vertex_mapping), PIPE_BUFFER, + PIPE_BIND_VERTEX_BUFFER); /* Figure out GLSL support. */ glsl_feature_level = screen->get_param(screen, PIPE_CAP_GLSL_FEATURE_LEVEL); - ctx->Const.GLSLVersion = glsl_feature_level; + consts->GLSLVersion = glsl_feature_level; if (glsl_feature_level >= 330) - ctx->Const.GLSLVersion = 330; + consts->GLSLVersion = 330; - _mesa_override_glsl_version(st->ctx); + _mesa_override_glsl_version(consts); - if (st->options.force_glsl_version > 0 && - st->options.force_glsl_version <= ctx->Const.GLSLVersion) { - ctx->Const.ForceGLSLVersion = st->options.force_glsl_version; + if (options->force_glsl_version > 0 && + options->force_glsl_version <= consts->GLSLVersion) { + consts->ForceGLSLVersion = options->force_glsl_version; } + if (glsl_feature_level >= 400) + extensions->ARB_gpu_shader5 = GL_TRUE; + /* This extension needs full OpenGL 3.2, but we don't know if that's * supported at this point. Only check the GLSL version. */ - if (ctx->Const.GLSLVersion >= 150 && + if (consts->GLSLVersion >= 150 && screen->get_param(screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT)) { - ctx->Extensions.AMD_vertex_shader_layer = GL_TRUE; + extensions->AMD_vertex_shader_layer = GL_TRUE; } - if (ctx->Const.GLSLVersion >= 130) { - ctx->Const.NativeIntegers = GL_TRUE; - ctx->Const.MaxClipPlanes = 8; + if (consts->GLSLVersion >= 130) { + consts->NativeIntegers = GL_TRUE; + consts->MaxClipPlanes = 8; /* Extensions that either depend on GLSL 1.30 or are a subset thereof. */ - ctx->Extensions.ARB_conservative_depth = GL_TRUE; - ctx->Extensions.ARB_shading_language_packing = GL_TRUE; - ctx->Extensions.OES_depth_texture_cube_map = GL_TRUE; - ctx->Extensions.ARB_shading_language_420pack = GL_TRUE; - ctx->Extensions.ARB_texture_query_levels = GL_TRUE; - - if (!st->options.disable_shader_bit_encoding) { - ctx->Extensions.ARB_shader_bit_encoding = GL_TRUE; + extensions->ARB_conservative_depth = GL_TRUE; + extensions->ARB_shading_language_packing = GL_TRUE; + extensions->OES_depth_texture_cube_map = GL_TRUE; + extensions->ARB_shading_language_420pack = GL_TRUE; + extensions->ARB_texture_query_levels = GL_TRUE; + + if (!options->disable_shader_bit_encoding) { + extensions->ARB_shader_bit_encoding = GL_TRUE; } - ctx->Extensions.EXT_shader_integer_mix = GL_TRUE; + extensions->EXT_shader_integer_mix = GL_TRUE; } else { /* Optional integer support for GLSL 1.2. */ if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS) && screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS)) { - ctx->Const.NativeIntegers = GL_TRUE; + consts->NativeIntegers = GL_TRUE; - ctx->Extensions.EXT_shader_integer_mix = GL_TRUE; + extensions->EXT_shader_integer_mix = GL_TRUE; } } /* Below are the cases which cannot be moved into tables easily. */ - if (!ctx->Mesa_DXTn && !st->options.force_s3tc_enable) { - ctx->Extensions.EXT_texture_compression_s3tc = GL_FALSE; - ctx->Extensions.ANGLE_texture_compression_dxt = GL_FALSE; + if (!has_lib_dxtc && !options->force_s3tc_enable) { + extensions->EXT_texture_compression_s3tc = GL_FALSE; + extensions->ANGLE_texture_compression_dxt = GL_FALSE; } if (screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { #if 0 /* XXX re-enable when GLSL compiler again supports geometry shaders */ - ctx->Extensions.ARB_geometry_shader4 = GL_TRUE; + extensions->ARB_geometry_shader4 = GL_TRUE; #endif } - ctx->Extensions.NV_primitive_restart = GL_TRUE; + extensions->NV_primitive_restart = GL_TRUE; if (!screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { - ctx->Const.PrimitiveRestartInSoftware = GL_TRUE; + consts->PrimitiveRestartInSoftware = GL_TRUE; } /* ARB_color_buffer_float. */ if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { - ctx->Extensions.ARB_color_buffer_float = GL_TRUE; - - if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) { - st->clamp_vert_color_in_shader = TRUE; - } - - if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) { - st->clamp_frag_color_in_shader = TRUE; - } - - /* For drivers which cannot do color clamping, it's better to just - * disable ARB_color_buffer_float in the core profile, because - * the clamping is deprecated there anyway. */ - if (ctx->API == API_OPENGL_CORE && - (st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) { - st->clamp_vert_color_in_shader = GL_FALSE; - st->clamp_frag_color_in_shader = GL_FALSE; - ctx->Extensions.ARB_color_buffer_float = GL_FALSE; - } + extensions->ARB_color_buffer_float = GL_TRUE; } if (screen->fence_finish) { - ctx->Extensions.ARB_sync = GL_TRUE; + extensions->ARB_sync = GL_TRUE; } /* Maximum sample count. */ - for (i = 16; i > 0; --i) { - enum pipe_format pformat = st_choose_format(st, GL_RGBA, - GL_NONE, GL_NONE, - PIPE_TEXTURE_2D, i, - PIPE_BIND_RENDER_TARGET, FALSE); - if (pformat != PIPE_FORMAT_NONE) { - ctx->Const.MaxSamples = i; - ctx->Const.MaxColorTextureSamples = i; - break; - } + { + enum pipe_format color_formats[] = { + PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_FORMAT_A8B8G8R8_UNORM, + }; + enum pipe_format depth_formats[] = { + PIPE_FORMAT_Z16_UNORM, + PIPE_FORMAT_Z24X8_UNORM, + PIPE_FORMAT_X8Z24_UNORM, + PIPE_FORMAT_Z32_UNORM, + PIPE_FORMAT_Z32_FLOAT + }; + enum pipe_format int_formats[] = { + PIPE_FORMAT_R8G8B8A8_SINT + }; + + consts->MaxSamples = + get_max_samples_for_formats(screen, Elements(color_formats), + color_formats, 16, + PIPE_BIND_RENDER_TARGET); + + consts->MaxColorTextureSamples = + get_max_samples_for_formats(screen, Elements(color_formats), + color_formats, consts->MaxSamples, + PIPE_BIND_SAMPLER_VIEW); + + consts->MaxDepthTextureSamples = + get_max_samples_for_formats(screen, Elements(depth_formats), + depth_formats, consts->MaxSamples, + PIPE_BIND_SAMPLER_VIEW); + + consts->MaxIntegerSamples = + get_max_samples_for_formats(screen, Elements(int_formats), + int_formats, consts->MaxSamples, + PIPE_BIND_SAMPLER_VIEW); } - for (i = ctx->Const.MaxSamples; i > 0; --i) { - enum pipe_format pformat = st_choose_format(st, GL_DEPTH_STENCIL, - GL_NONE, GL_NONE, - PIPE_TEXTURE_2D, i, - PIPE_BIND_DEPTH_STENCIL, FALSE); - if (pformat != PIPE_FORMAT_NONE) { - ctx->Const.MaxDepthTextureSamples = i; - break; - } - } - for (i = ctx->Const.MaxSamples; i > 0; --i) { - enum pipe_format pformat = st_choose_format(st, GL_RGBA_INTEGER, - GL_NONE, GL_NONE, - PIPE_TEXTURE_2D, i, - PIPE_BIND_RENDER_TARGET, FALSE); - if (pformat != PIPE_FORMAT_NONE) { - ctx->Const.MaxIntegerSamples = i; - break; - } - } - if (ctx->Const.MaxSamples == 1) { + if (consts->MaxSamples == 1) { /* one sample doesn't really make sense */ - ctx->Const.MaxSamples = 0; + consts->MaxSamples = 0; } - else if (ctx->Const.MaxSamples >= 2) { - ctx->Extensions.EXT_framebuffer_multisample = GL_TRUE; - ctx->Extensions.EXT_framebuffer_multisample_blit_scaled = GL_TRUE; + else if (consts->MaxSamples >= 2) { + extensions->EXT_framebuffer_multisample = GL_TRUE; + extensions->EXT_framebuffer_multisample_blit_scaled = GL_TRUE; } - if (ctx->Const.MaxSamples == 0 && screen->get_param(screen, PIPE_CAP_FAKE_SW_MSAA)) { - ctx->Const.FakeSWMSAA = GL_TRUE; - ctx->Extensions.EXT_framebuffer_multisample = GL_TRUE; - ctx->Extensions.EXT_framebuffer_multisample_blit_scaled = GL_TRUE; - ctx->Extensions.ARB_texture_multisample = GL_TRUE; + if (consts->MaxSamples == 0 && screen->get_param(screen, PIPE_CAP_FAKE_SW_MSAA)) { + consts->FakeSWMSAA = GL_TRUE; + extensions->EXT_framebuffer_multisample = GL_TRUE; + extensions->EXT_framebuffer_multisample_blit_scaled = GL_TRUE; + extensions->ARB_texture_multisample = GL_TRUE; } - if (ctx->Const.MaxDualSourceDrawBuffers > 0 && - !st->options.disable_blend_func_extended) - ctx->Extensions.ARB_blend_func_extended = GL_TRUE; + if (consts->MaxDualSourceDrawBuffers > 0 && + !options->disable_blend_func_extended) + extensions->ARB_blend_func_extended = GL_TRUE; - st->has_time_elapsed = - screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED); - - if (st->has_time_elapsed || - ctx->Extensions.ARB_timer_query) { - ctx->Extensions.EXT_timer_query = GL_TRUE; + if (screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED) || + extensions->ARB_timer_query) { + extensions->EXT_timer_query = GL_TRUE; } - if (ctx->Extensions.ARB_transform_feedback2 && - ctx->Extensions.ARB_draw_instanced) { - ctx->Extensions.ARB_transform_feedback_instanced = GL_TRUE; + if (extensions->ARB_transform_feedback2 && + extensions->ARB_draw_instanced) { + extensions->ARB_transform_feedback_instanced = GL_TRUE; } - if (st->options.force_glsl_extensions_warn) - ctx->Const.ForceGLSLExtensionsWarn = 1; + if (options->force_glsl_extensions_warn) + consts->ForceGLSLExtensionsWarn = 1; - if (st->options.disable_glsl_line_continuations) - ctx->Const.DisableGLSLLineContinuations = 1; + if (options->disable_glsl_line_continuations) + consts->DisableGLSLLineContinuations = 1; - if (st->options.allow_glsl_extension_directive_midshader) - ctx->Const.AllowGLSLExtensionDirectiveMidShader = GL_TRUE; + if (options->allow_glsl_extension_directive_midshader) + consts->AllowGLSLExtensionDirectiveMidShader = GL_TRUE; - ctx->Const.MinMapBufferAlignment = + consts->MinMapBufferAlignment = screen->get_param(screen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT); if (screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) { - ctx->Extensions.ARB_texture_buffer_object = GL_TRUE; + extensions->ARB_texture_buffer_object = GL_TRUE; - ctx->Const.MaxTextureBufferSize = + consts->MaxTextureBufferSize = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE), (1u << 31) - 1); - ctx->Const.TextureBufferOffsetAlignment = + consts->TextureBufferOffsetAlignment = screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT); - if (ctx->Const.TextureBufferOffsetAlignment) - ctx->Extensions.ARB_texture_buffer_range = GL_TRUE; + if (consts->TextureBufferOffsetAlignment) + extensions->ARB_texture_buffer_range = GL_TRUE; - init_format_extensions(st, tbo_rgb32, Elements(tbo_rgb32), - PIPE_BUFFER, PIPE_BIND_SAMPLER_VIEW); + init_format_extensions(screen, extensions, tbo_rgb32, + Elements(tbo_rgb32), PIPE_BUFFER, + PIPE_BIND_SAMPLER_VIEW); } if (screen->get_param(screen, PIPE_CAP_MIXED_FRAMEBUFFER_SIZES)) { - ctx->Extensions.ARB_framebuffer_object = GL_TRUE; + extensions->ARB_framebuffer_object = GL_TRUE; } /* Unpacking a varying in the fragment shader costs 1 texture indirection. @@ -809,21 +836,49 @@ void st_init_extensions(struct st_context *st) /* We can't disable varying packing if transform feedback is available, * because transform feedback code assumes a packed varying layout. */ - if (!ctx->Extensions.EXT_transform_feedback) - ctx->Const.DisableVaryingPacking = GL_TRUE; + if (!extensions->EXT_transform_feedback) + consts->DisableVaryingPacking = GL_TRUE; } - if (ctx->API == API_OPENGL_CORE) { - ctx->Const.MaxViewports = screen->get_param(screen, PIPE_CAP_MAX_VIEWPORTS); - if (ctx->Const.MaxViewports >= 16) { - ctx->Const.ViewportBounds.Min = -16384.0; - ctx->Const.ViewportBounds.Max = 16384.0; - ctx->Extensions.ARB_viewport_array = GL_TRUE; - ctx->Extensions.ARB_fragment_layer_viewport = GL_TRUE; - if (ctx->Extensions.AMD_vertex_shader_layer) - ctx->Extensions.AMD_vertex_shader_viewport_index = GL_TRUE; + if (api == API_OPENGL_CORE) { + consts->MaxViewports = screen->get_param(screen, PIPE_CAP_MAX_VIEWPORTS); + if (consts->MaxViewports >= 16) { + consts->ViewportBounds.Min = -16384.0; + consts->ViewportBounds.Max = 16384.0; + extensions->ARB_viewport_array = GL_TRUE; + extensions->ARB_fragment_layer_viewport = GL_TRUE; + if (extensions->AMD_vertex_shader_layer) + extensions->AMD_vertex_shader_viewport_index = GL_TRUE; } } - if (ctx->Const.MaxProgramTextureGatherComponents > 0) - ctx->Extensions.ARB_texture_gather = GL_TRUE; + if (consts->MaxProgramTextureGatherComponents > 0) + extensions->ARB_texture_gather = GL_TRUE; + + /* GL_ARB_ES3_compatibility. + * + * Assume that ES3 is supported if GLSL 3.30 is supported. + * (OpenGL 3.3 is a requirement for that extension.) + */ + if (consts->GLSLVersion >= 330 && + /* Requirements for ETC2 emulation. */ + screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_R16_SNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_R16G16_SNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW)) { + extensions->ARB_ES3_compatibility = GL_TRUE; + } } diff --git a/mesalib/src/mesa/state_tracker/st_extensions.h b/mesalib/src/mesa/state_tracker/st_extensions.h index d098ed074..8d2724d67 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.h +++ b/mesalib/src/mesa/state_tracker/st_extensions.h @@ -31,10 +31,18 @@ struct st_context; - -extern void st_init_limits(struct st_context *st); - -extern void st_init_extensions(struct st_context *st); +struct pipe_screen; + +extern void st_init_limits(struct pipe_screen *screen, + struct gl_constants *c, + struct gl_extensions *extensions); + +extern void st_init_extensions(struct pipe_screen *screen, + gl_api api, + struct gl_constants *consts, + struct gl_extensions *extensions, + struct st_config_options *options, + boolean has_lib_dxtc); #endif /* ST_EXTENSIONS_H */ diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index 409079bd4..b5e03b0f8 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -54,7 +54,7 @@ * Translate Mesa format to Gallium format. */ enum pipe_format -st_mesa_format_to_pipe_format(mesa_format mesaFormat) +st_mesa_format_to_pipe_format(struct st_context *st, mesa_format mesaFormat) { switch (mesaFormat) { case MESA_FORMAT_A8B8G8R8_UNORM: @@ -323,8 +323,19 @@ st_mesa_format_to_pipe_format(mesa_format mesaFormat) case MESA_FORMAT_LA_LATC2_SNORM: return PIPE_FORMAT_LATC2_SNORM; + /* The destination RGBA format mustn't be changed, because it's also + * a destination format of the unpack/decompression function. */ case MESA_FORMAT_ETC1_RGB8: - return PIPE_FORMAT_ETC1_RGB8; + return st->has_etc1 ? PIPE_FORMAT_ETC1_RGB8 : PIPE_FORMAT_R8G8B8A8_UNORM; + + case MESA_FORMAT_BPTC_RGBA_UNORM: + return PIPE_FORMAT_BPTC_RGBA_UNORM; + case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM: + return PIPE_FORMAT_BPTC_SRGBA; + case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT: + return PIPE_FORMAT_BPTC_RGB_FLOAT; + case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT: + return PIPE_FORMAT_BPTC_RGB_UFLOAT; /* signed normalized formats */ case MESA_FORMAT_R_SNORM8: @@ -402,6 +413,26 @@ st_mesa_format_to_pipe_format(mesa_format mesaFormat) case MESA_FORMAT_B8G8R8X8_SRGB: return PIPE_FORMAT_B8G8R8X8_SRGB; + /* ETC2 formats are emulated as uncompressed ones. + * The destination formats mustn't be changed, because they are also + * destination formats of the unpack/decompression function. */ + case MESA_FORMAT_ETC2_RGB8: + case MESA_FORMAT_ETC2_RGBA8_EAC: + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + return PIPE_FORMAT_R8G8B8A8_UNORM; + case MESA_FORMAT_ETC2_SRGB8: + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + return PIPE_FORMAT_B8G8R8A8_SRGB; + case MESA_FORMAT_ETC2_R11_EAC: + return PIPE_FORMAT_R16_UNORM; + case MESA_FORMAT_ETC2_RG11_EAC: + return PIPE_FORMAT_R16G16_UNORM; + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + return PIPE_FORMAT_R16_SNORM; + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + return PIPE_FORMAT_R16G16_SNORM; + default: return PIPE_FORMAT_NONE; } @@ -685,6 +716,15 @@ st_pipe_format_to_mesa_format(enum pipe_format format) case PIPE_FORMAT_ETC1_RGB8: return MESA_FORMAT_ETC1_RGB8; + case PIPE_FORMAT_BPTC_RGBA_UNORM: + return MESA_FORMAT_BPTC_RGBA_UNORM; + case PIPE_FORMAT_BPTC_SRGBA: + return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM; + case PIPE_FORMAT_BPTC_RGB_FLOAT: + return MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT; + case PIPE_FORMAT_BPTC_RGB_UFLOAT: + return MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT; + /* signed normalized formats */ case PIPE_FORMAT_R8_SNORM: return MESA_FORMAT_R_SNORM8; @@ -775,13 +815,21 @@ st_pipe_format_to_mesa_format(enum pipe_format format) * Mesa formats to Gallium formats and back again. */ static void -test_format_conversion(void) +test_format_conversion(struct st_context *st) { GLuint i; /* test all Mesa formats */ for (i = 1; i < MESA_FORMAT_COUNT; i++) { - enum pipe_format pf = st_mesa_format_to_pipe_format(i); + enum pipe_format pf; + + /* ETC formats are translated differently, skip them. */ + if (_mesa_is_format_etc2(i)) + continue; + if (i == MESA_FORMAT_ETC1_RGB8 && !st->has_etc1) + continue; + + pf = st_mesa_format_to_pipe_format(st, i); if (pf != PIPE_FORMAT_NONE) { mesa_format mf = st_pipe_format_to_mesa_format(pf); assert(mf == i); @@ -791,8 +839,13 @@ test_format_conversion(void) /* Test all Gallium formats */ for (i = 1; i < PIPE_FORMAT_COUNT; i++) { mesa_format mf = st_pipe_format_to_mesa_format(i); + + /* ETC formats are translated differently, skip them. */ + if (i == PIPE_FORMAT_ETC1_RGB8 && !st->has_etc1) + continue; + if (mf != MESA_FORMAT_NONE) { - enum pipe_format pf = st_mesa_format_to_pipe_format(mf); + enum pipe_format pf = st_mesa_format_to_pipe_format(st, mf); assert(pf == i); } } @@ -1238,6 +1291,24 @@ static const struct format_mapping format_map[] = { { PIPE_FORMAT_ETC1_RGB8, 0 } }, + /* BPTC */ + { + { GL_COMPRESSED_RGBA_BPTC_UNORM, 0 }, + { PIPE_FORMAT_BPTC_RGBA_UNORM, 0 }, + }, + { + { GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, 0 }, + { PIPE_FORMAT_BPTC_SRGBA, 0 }, + }, + { + { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, 0 }, + { PIPE_FORMAT_BPTC_RGB_FLOAT, 0 }, + }, + { + { GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, 0 }, + { PIPE_FORMAT_BPTC_RGB_UFLOAT, 0 }, + }, + /* signed/unsigned integer formats. */ { @@ -1680,7 +1751,7 @@ st_choose_format(struct st_context *st, GLenum internalFormat, { static boolean firstCall = TRUE; if (firstCall) { - test_format_conversion(); + test_format_conversion(st); firstCall = FALSE; } } @@ -1746,9 +1817,10 @@ st_choose_renderbuffer_format(struct st_context *st, * If no format is supported, return PIPE_FORMAT_NONE. */ enum pipe_format -st_choose_matching_format(struct pipe_screen *screen, unsigned bind, +st_choose_matching_format(struct st_context *st, unsigned bind, GLenum format, GLenum type, GLboolean swapBytes) { + struct pipe_screen *screen = st->pipe->screen; mesa_format mesa_format; for (mesa_format = 1; mesa_format < MESA_FORMAT_COUNT; mesa_format++) { @@ -1764,7 +1836,8 @@ st_choose_matching_format(struct pipe_screen *screen, unsigned bind, if (_mesa_format_matches_format_and_type(mesa_format, format, type, swapBytes)) { - enum pipe_format format = st_mesa_format_to_pipe_format(mesa_format); + enum pipe_format format = + st_mesa_format_to_pipe_format(st, mesa_format); if (format && screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, @@ -1834,16 +1907,14 @@ st_ChooseTextureFormat(struct gl_context *ctx, GLenum target, * with the "format". */ if (iformat == baseFormat && iformat == basePackFormat) { - pFormat = st_choose_matching_format(st->pipe->screen, bindings, - format, type, + pFormat = st_choose_matching_format(st, bindings, format, type, ctx->Unpack.SwapBytes); if (pFormat != PIPE_FORMAT_NONE) return st_pipe_format_to_mesa_format(pFormat); /* try choosing format again, this time without render target bindings */ - pFormat = st_choose_matching_format(st->pipe->screen, - PIPE_BIND_SAMPLER_VIEW, + pFormat = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW, format, type, ctx->Unpack.SwapBytes); if (pFormat != PIPE_FORMAT_NONE) diff --git a/mesalib/src/mesa/state_tracker/st_format.h b/mesalib/src/mesa/state_tracker/st_format.h index ce1e2306d..90e00e8eb 100644 --- a/mesalib/src/mesa/state_tracker/st_format.h +++ b/mesalib/src/mesa/state_tracker/st_format.h @@ -41,7 +41,7 @@ struct pipe_screen; extern enum pipe_format -st_mesa_format_to_pipe_format(mesa_format mesaFormat); +st_mesa_format_to_pipe_format(struct st_context *st, mesa_format mesaFormat); extern mesa_format st_pipe_format_to_mesa_format(enum pipe_format pipeFormat); @@ -58,7 +58,7 @@ st_choose_renderbuffer_format(struct st_context *st, GLenum internalFormat, unsigned sample_count); extern enum pipe_format -st_choose_matching_format(struct pipe_screen *screen, unsigned bind, +st_choose_matching_format(struct st_context *st, unsigned bind, GLenum format, GLenum type, GLboolean swapBytes); extern mesa_format diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 0290553c6..84bdc4f06 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -245,7 +245,8 @@ public: ir_instruction *ir; GLboolean cond_update; bool saturate; - int sampler; /**< sampler index */ + st_src_reg sampler; /**< sampler register */ + int sampler_array_size; /**< 1-based size of sampler array, 1 if not array */ int tex_target; /**< One of TEXTURE_*_INDEX */ GLboolean tex_shadow; @@ -476,6 +477,7 @@ static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP, GLSL_T static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 0); static st_dst_reg address_reg2 = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 1); +static st_dst_reg sampler_reladdr = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 2); static void fail_link(struct gl_shader_program *prog, const char *fmt, ...) PRINTFLIKE(2, 3); @@ -1460,9 +1462,15 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) break; case ir_unop_dFdx: + case ir_unop_dFdx_coarse: emit(ir, TGSI_OPCODE_DDX, result_dst, op[0]); break; + case ir_unop_dFdx_fine: + emit(ir, TGSI_OPCODE_DDX_FINE, result_dst, op[0]); + break; case ir_unop_dFdy: + case ir_unop_dFdy_coarse: + case ir_unop_dFdy_fine: { /* The X component contains 1 or -1 depending on whether the framebuffer * is a FBO or the window system buffer, respectively. @@ -1483,7 +1491,8 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) st_src_reg temp = get_temp(glsl_type::vec4_type); emit(ir, TGSI_OPCODE_MUL, st_dst_reg(temp), transform_y, op[0]); - emit(ir, TGSI_OPCODE_DDY, result_dst, temp); + emit(ir, ir->operation == ir_unop_dFdy_fine ? + TGSI_OPCODE_DDY_FINE : TGSI_OPCODE_DDY, result_dst, temp); break; } @@ -2799,6 +2808,8 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) glsl_to_tgsi_instruction *inst = NULL; unsigned opcode = TGSI_OPCODE_NOP; const glsl_type *sampler_type = ir->sampler->type; + ir_rvalue *sampler_index = + _mesa_get_sampler_array_nonconst_index(ir->sampler); bool is_cube_array = false; unsigned i; @@ -3016,6 +3027,11 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) coord_dst.writemask = WRITEMASK_XYZW; } + if (sampler_index) { + sampler_index->accept(this); + emit_arl(ir, sampler_reladdr, this->result); + } + if (opcode == TGSI_OPCODE_TXD) inst = emit(ir, opcode, result_dst, coord, dx, dy); else if (opcode == TGSI_OPCODE_TXQ) { @@ -3045,9 +3061,17 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) if (ir->shadow_comparitor) inst->tex_shadow = GL_TRUE; - inst->sampler = _mesa_get_sampler_uniform_value(ir->sampler, - this->shader_program, - this->prog); + inst->sampler.index = _mesa_get_sampler_uniform_value(ir->sampler, + this->shader_program, + this->prog); + if (sampler_index) { + inst->sampler.reladdr = ralloc(mem_ctx, st_src_reg); + memcpy(inst->sampler.reladdr, &sampler_reladdr, sizeof(sampler_reladdr)); + inst->sampler_array_size = + ir->sampler->as_dereference_array()->array->type->array_size(); + } else { + inst->sampler_array_size = 1; + } if (ir->offset) { for (i = 0; i < MAX_GLSL_TEXTURE_OFFSET && offset[i].file != PROGRAM_UNDEFINED; i++) @@ -3215,10 +3239,12 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog) foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions) { if (is_tex_instruction(inst->op)) { - v->samplers_used |= 1 << inst->sampler; + for (int i = 0; i < inst->sampler_array_size; i++) { + v->samplers_used |= 1 << (inst->sampler.index + i); - if (inst->tex_shadow) { - prog->ShadowSamplers |= 1 << inst->sampler; + if (inst->tex_shadow) { + prog->ShadowSamplers |= 1 << (inst->sampler.index + i); + } } } } @@ -3952,7 +3978,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, src0 = v->get_temp(glsl_type::vec4_type); dst0 = st_dst_reg(src0); inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord); - inst->sampler = 0; + inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; prog->InputsRead |= VARYING_BIT_TEX0; @@ -3991,14 +4017,16 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */ temp_dst.writemask = WRITEMASK_XY; /* write R,G */ inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0); - inst->sampler = 1; + inst->sampler.index = 1; + inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */ src0.swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W); temp_dst.writemask = WRITEMASK_ZW; /* write B,A */ inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0); - inst->sampler = 1; + inst->sampler.index = 1; + inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; prog->SamplersUsed |= (1 << 1); /* mark sampler 1 as used */ @@ -4079,7 +4107,8 @@ get_bitmap_visitor(struct st_fragment_program *fp, src0 = v->get_temp(glsl_type::vec4_type); dst0 = st_dst_reg(src0); inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord); - inst->sampler = samplerIndex; + inst->sampler.index = samplerIndex; + inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; prog->InputsRead |= VARYING_BIT_TEX0; @@ -4135,7 +4164,7 @@ struct st_translate { struct ureg_src *immediates; struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS]; struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS]; - struct ureg_dst address[2]; + struct ureg_dst address[3]; struct ureg_src samplers[PIPE_MAX_SAMPLERS]; struct ureg_src systemValues[SYSTEM_VALUE_MAX]; struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; @@ -4546,7 +4575,11 @@ compile_tgsi_instruction(struct st_translate *t, case TGSI_OPCODE_TXL2: case TGSI_OPCODE_TG4: case TGSI_OPCODE_LODQ: - src[num_src++] = t->samplers[inst->sampler]; + src[num_src] = t->samplers[inst->sampler.index]; + if (inst->sampler.reladdr) + src[num_src] = + ureg_src_indirect(src[num_src], ureg_src(t->address[2])); + num_src++; for (i = 0; i < inst->tex_offset_num_offset; i++) { texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i], i); } @@ -4977,10 +5010,9 @@ st_translate_program( /* Declare address register. */ if (program->num_address_regs > 0) { - assert(program->num_address_regs <= 2); - t->address[0] = ureg_DECL_address(ureg); - if (program->num_address_regs == 2) - t->address[1] = ureg_DECL_address(ureg); + assert(program->num_address_regs <= 3); + for (int i = 0; i < program->num_address_regs; i++) + t->address[i] = ureg_DECL_address(ureg); } /* Declare misc input registers @@ -5176,7 +5208,7 @@ get_mesa_program(struct gl_context *ctx, GLenum target = _mesa_shader_stage_to_program(shader->Stage); bool progress; struct gl_shader_compiler_options *options = - &ctx->ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)]; + &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)]; struct pipe_screen *pscreen = ctx->st->pipe->screen; unsigned ptarget = shader_stage_to_ptarget(shader->Stage); @@ -5365,7 +5397,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) bool progress; exec_list *ir = prog->_LinkedShaders[i]->ir; const struct gl_shader_compiler_options *options = - &ctx->ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(prog->_LinkedShaders[i]->Type)]; + &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(prog->_LinkedShaders[i]->Type)]; /* If there are forms of indirect addressing that the driver * cannot handle, perform the lowering pass. diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 706af7fd1..7bc33268e 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -26,6 +26,7 @@ */ #include "main/mtypes.h" +#include "main/extensions.h" #include "main/context.h" #include "main/texobj.h" #include "main/teximage.h" @@ -38,6 +39,7 @@ #include "st_texture.h" #include "st_context.h" +#include "st_extensions.h" #include "st_format.h" #include "st_cb_fbo.h" #include "st_cb_flush.h" @@ -910,6 +912,41 @@ st_manager_add_color_renderbuffer(struct st_context *st, return TRUE; } +static unsigned get_version(struct pipe_screen *screen, + struct st_config_options *options, gl_api api) +{ + struct gl_constants consts = {0}; + struct gl_extensions extensions = {0}; + GLuint version; + + if ((api == API_OPENGL_COMPAT || api == API_OPENGL_CORE) && + _mesa_override_gl_version_contextless(&consts, &api, &version)) { + return version; + } + + _mesa_init_constants(&consts, api); + _mesa_init_extensions(&extensions); + + st_init_limits(screen, &consts, &extensions); + st_init_extensions(screen, api, &consts, &extensions, options, GL_TRUE); + + return _mesa_get_version(&extensions, &consts, api); +} + +static void +st_api_query_versions(struct st_api *stapi, struct st_manager *sm, + struct st_config_options *options, + int *gl_core_version, + int *gl_compat_version, + int *gl_es1_version, + int *gl_es2_version) +{ + *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE); + *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT); + *gl_es1_version = get_version(sm->screen, options, API_OPENGLES); + *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2); +} + static const struct st_api st_gl_api = { "Mesa " PACKAGE_VERSION, ST_API_OPENGL, @@ -920,6 +957,7 @@ static const struct st_api st_gl_api = { 0, ST_API_FEATURE_MS_VISUALS_MASK, st_api_destroy, + st_api_query_versions, st_api_get_proc_address, st_api_create_context, st_api_make_current, diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c index c14882142..af9b7675f 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.c +++ b/mesalib/src/mesa/state_tracker/st_texture.c @@ -197,7 +197,8 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture, * Check if a texture image can be pulled into a unified mipmap texture. */ GLboolean -st_texture_match_image(const struct pipe_resource *pt, +st_texture_match_image(struct st_context *st, + const struct pipe_resource *pt, const struct gl_texture_image *image) { GLuint ptWidth, ptHeight, ptDepth, ptLayers; @@ -209,7 +210,7 @@ st_texture_match_image(const struct pipe_resource *pt, /* Check if this image's format matches the established texture's format. */ - if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format) + if (st_mesa_format_to_pipe_format(st, image->TexFormat) != pt->format) return GL_FALSE; st_gl_texture_dims_to_pipe_dims(image->TexObject->Target, @@ -269,14 +270,15 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, unsigned new_size = z + 1; stImage->transfer = realloc(stImage->transfer, - new_size * sizeof(void*)); + new_size * sizeof(struct st_texture_image_transfer)); memset(&stImage->transfer[stImage->num_transfers], 0, - (new_size - stImage->num_transfers) * sizeof(void*)); + (new_size - stImage->num_transfers) * + sizeof(struct st_texture_image_transfer)); stImage->num_transfers = new_size; } - assert(!stImage->transfer[z]); - stImage->transfer[z] = *transfer; + assert(!stImage->transfer[z].transfer); + stImage->transfer[z].transfer = *transfer; } return map; } @@ -288,7 +290,7 @@ st_texture_image_unmap(struct st_context *st, { struct pipe_context *pipe = st->pipe; struct pipe_transfer **transfer = - &stImage->transfer[slice + stImage->base.Face]; + &stImage->transfer[slice + stImage->base.Face].transfer; DBG("%s\n", __FUNCTION__); diff --git a/mesalib/src/mesa/state_tracker/st_texture.h b/mesalib/src/mesa/state_tracker/st_texture.h index affb56812..ce1cf8b0a 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.h +++ b/mesalib/src/mesa/state_tracker/st_texture.h @@ -38,6 +38,16 @@ struct pipe_resource; +struct st_texture_image_transfer { + struct pipe_transfer *transfer; + + /* For ETC fallback. */ + GLubyte *temp_data; /**< Temporary ETC texture storage. */ + unsigned temp_stride; /**< Stride of the ETC texture storage. */ + GLubyte *map; /**< Saved map pointer of the uncompressed transfer. */ +}; + + /** * Subclass of gl_texure_image. */ @@ -59,7 +69,7 @@ struct st_texture_image /* List of transfers, allocated on demand. * transfer[layer] is a mapping for that layer. */ - struct pipe_transfer **transfer; + struct st_texture_image_transfer *transfer; unsigned num_transfers; }; @@ -189,7 +199,8 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture, /* Check if an image fits into an existing texture object. */ extern GLboolean -st_texture_match_image(const struct pipe_resource *pt, +st_texture_match_image(struct st_context *st, + const struct pipe_resource *pt, const struct gl_texture_image *image); /* Return a pointer to an image within a texture. Return image stride as diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index aef023217..38d71caa3 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -512,6 +512,30 @@ texfetch_funcs[] = fetch_compressed, fetch_compressed, fetch_compressed + }, + { + MESA_FORMAT_BPTC_RGBA_UNORM, + fetch_compressed, + fetch_compressed, + fetch_compressed + }, + { + MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM, + fetch_compressed, + fetch_compressed, + fetch_compressed + }, + { + MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT, + fetch_compressed, + fetch_compressed, + fetch_compressed + }, + { + MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT, + fetch_compressed, + fetch_compressed, + fetch_compressed } }; diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index 9c161ccca..3f7058da1 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -1890,6 +1890,12 @@ _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count) vbo_exec_DrawArrays(mode, first, count); } +void GLAPIENTRY +_mesa_DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, + GLsizei primcount) +{ + vbo_exec_DrawArraysInstanced(mode, first, count, primcount); +} void GLAPIENTRY _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, |