diff options
Diffstat (limited to 'mesalib/src/mesa/main')
23 files changed, 1216 insertions, 34 deletions
diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c index f0b525fa0..077c5fca3 100644 --- a/mesalib/src/mesa/main/clear.c +++ b/mesalib/src/mesa/main/clear.c @@ -179,7 +179,11 @@ _mesa_Clear( GLbitfield mask ) if (mask & GL_COLOR_BUFFER_BIT) { GLuint i; for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - bufferMask |= (1 << ctx->DrawBuffer->_ColorDrawBufferIndexes[i]); + GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; + + if (buf >= 0) { + bufferMask |= 1 << buf; + } } } @@ -274,7 +278,7 @@ make_color_buffer_mask(struct gl_context *ctx, GLint drawbuffer) break; default: { - GLuint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; + GLint buf = ctx->DrawBuffer->_ColorDrawBufferIndexes[drawbuffer]; if (buf >= 0 && att[buf].Renderbuffer) { mask |= 1 << buf; diff --git a/mesalib/src/mesa/main/condrender.c b/mesalib/src/mesa/main/condrender.c index 2632f7a1a..0ad1e5c2a 100644 --- a/mesalib/src/mesa/main/condrender.c +++ b/mesalib/src/mesa/main/condrender.c @@ -40,17 +40,38 @@ void GLAPIENTRY _mesa_BeginConditionalRender(GLuint queryId, GLenum mode) { - struct gl_query_object *q; + struct gl_query_object *q = NULL; GET_CURRENT_CONTEXT(ctx); - if (!ctx->Extensions.NV_conditional_render || ctx->Query.CondRenderQuery || - queryId == 0) { + /* Section 2.14 (Conditional Rendering) of the OpenGL 3.0 spec says: + * + * "If BeginConditionalRender is called while conditional rendering is + * in progress, or if EndConditionalRender is called while conditional + * rendering is not in progress, the error INVALID_OPERATION is + * generated." + */ + if (!ctx->Extensions.NV_conditional_render || ctx->Query.CondRenderQuery) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginConditionalRender()"); return; } ASSERT(ctx->Query.CondRenderMode == GL_NONE); + /* Section 2.14 (Conditional Rendering) of the OpenGL 3.0 spec says: + * + * "The error INVALID_VALUE is generated if <id> is not the name of an + * existing query object query." + */ + if (queryId != 0) + q = _mesa_lookup_query_object(ctx, queryId); + + if (!q) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBeginConditionalRender(bad queryId=%u)", queryId); + return; + } + ASSERT(q->Id == queryId); + switch (mode) { case GL_QUERY_WAIT: case GL_QUERY_NO_WAIT: @@ -64,14 +85,12 @@ _mesa_BeginConditionalRender(GLuint queryId, GLenum mode) return; } - q = _mesa_lookup_query_object(ctx, queryId); - if (!q) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glBeginConditionalRender(bad queryId=%u)", queryId); - return; - } - ASSERT(q->Id == queryId); - + /* Section 2.14 (Conditional Rendering) of the OpenGL 3.0 spec says: + * + * "The error INVALID_OPERATION is generated if <id> is the name of a + * query object with a target other than SAMPLES_PASSED, or <id> is the + * name of a query currently in progress." + */ if ((q->Target != GL_SAMPLES_PASSED && q->Target != GL_ANY_SAMPLES_PASSED && q->Target != GL_ANY_SAMPLES_PASSED_CONSERVATIVE) || q->Active) { diff --git a/mesalib/src/mesa/main/config.h b/mesalib/src/mesa/main/config.h index 22bbfa0cf..ff9da779b 100644 --- a/mesalib/src/mesa/main/config.h +++ b/mesalib/src/mesa/main/config.h @@ -175,6 +175,9 @@ #define MAX_COMBINED_ATOMIC_BUFFERS (MAX_UNIFORM_BUFFERS * 6) /* Size of an atomic counter in bytes according to ARB_shader_atomic_counters */ #define ATOMIC_COUNTER_SIZE 4 +#define MAX_IMAGE_UNIFORMS 16 +/* 6 is for vertex, hull, domain, geometry, fragment, and compute shader. */ +#define MAX_IMAGE_UNITS (MAX_IMAGE_UNIFORMS * 6) /*@}*/ /** diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 6e73691ea..6c084afa3 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -39,6 +39,7 @@ struct gl_buffer_object; struct gl_context; struct gl_display_list; struct gl_framebuffer; +struct gl_image_unit; struct gl_pixelstore_attrib; struct gl_program; struct gl_renderbuffer; @@ -484,7 +485,7 @@ struct dd_function_table { /** Enable or disable writing into the depth buffer */ void (*DepthMask)(struct gl_context *ctx, GLboolean flag); /** Specify mapping of depth values from NDC to window coordinates */ - void (*DepthRange)(struct gl_context *ctx, GLclampd nearval, GLclampd farval); + void (*DepthRange)(struct gl_context *ctx); /** Specify the current buffer for writing */ void (*DrawBuffer)( struct gl_context *ctx, GLenum buffer ); /** Specify the buffers for writing for fragment programs*/ @@ -524,7 +525,7 @@ struct dd_function_table { /** Set rasterization mode */ void (*RenderMode)(struct gl_context *ctx, GLenum mode ); /** Define the scissor box */ - void (*Scissor)(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h); + void (*Scissor)(struct gl_context *ctx); /** Select flat or smooth shading */ void (*ShadeModel)(struct gl_context *ctx, GLenum mode); /** OpenGL 2.0 two-sided StencilFunc */ @@ -546,7 +547,7 @@ struct dd_function_table { struct gl_texture_object *texObj, GLenum pname, const GLfloat *params); /** Set the viewport */ - void (*Viewport)(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h); + void (*Viewport)(struct gl_context *ctx); /*@}*/ @@ -910,6 +911,19 @@ struct dd_function_table { * non-zero status should be returned for the duration of the reset. */ GLenum (*GetGraphicsResetStatus)(struct gl_context *ctx); + + /** + * \name GL_ARB_shader_image_load_store interface. + */ + /** @{ */ + void (*BindImageTexture)(struct gl_context *ctx, + struct gl_image_unit *unit, + struct gl_texture_object *texObj, + GLint level, GLboolean layered, GLint layer, + GLenum access, GLenum format); + + void (*MemoryBarrier)(struct gl_context *ctx, GLbitfield barriers); + /** @} */ }; diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 89d47931a..2e0ccc3b6 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -126,6 +126,7 @@ static const struct extension extension_table[] = { { "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 }, { "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 }, { "GL_ARB_shader_bit_encoding", o(ARB_shader_bit_encoding), GL, 2010 }, + { "GL_ARB_shader_image_load_store", o(ARB_shader_image_load_store), GL, 2011 }, { "GL_ARB_shader_objects", o(dummy_true), GL, 2002 }, { "GL_ARB_shader_stencil_export", o(ARB_shader_stencil_export), GL, 2009 }, { "GL_ARB_shader_texture_lod", o(ARB_shader_texture_lod), GL, 2009 }, diff --git a/mesalib/src/mesa/main/format_pack.c b/mesalib/src/mesa/main/format_pack.c index 826fc10a6..41f5f99c1 100644 --- a/mesalib/src/mesa/main/format_pack.c +++ b/mesalib/src/mesa/main/format_pack.c @@ -1824,6 +1824,56 @@ pack_float_XBGR32323232_FLOAT(const GLfloat src[4], void *dst) d[3] = 1.0; } +/* MESA_FORMAT_ABGR2101010 */ + +static void +pack_ubyte_ABGR2101010(const GLubyte src[4], void *dst) +{ + GLuint *d = ((GLuint *) dst); + GLushort r = UBYTE_TO_USHORT(src[RCOMP]); + GLushort g = UBYTE_TO_USHORT(src[GCOMP]); + GLushort b = UBYTE_TO_USHORT(src[BCOMP]); + GLushort a = UBYTE_TO_USHORT(src[ACOMP]); + *d = PACK_COLOR_2101010_US(a, b, g, r); +} + +static void +pack_float_ABGR2101010(const GLfloat src[4], void *dst) +{ + GLuint *d = ((GLuint *) dst); + GLushort r, g, b, a; + UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]); + *d = PACK_COLOR_2101010_US(a, b, g, r); +} + +/* + * MESA_FORMAT_SIGNED_RG88 + */ + +static void +pack_float_SIGNED_RG88(const GLfloat src[4], void *dst) +{ + GLushort *d = (GLushort *) dst; + GLbyte r = FLOAT_TO_BYTE(CLAMP(src[RCOMP], -1.0f, 1.0f)); + GLbyte g = FLOAT_TO_BYTE(CLAMP(src[GCOMP], -1.0f, 1.0f)); + *d = (r << 8) | (g & 0xff); +} + +/* + * MESA_FORMAT_SIGNED_RG1616 + */ + +static void +pack_float_SIGNED_RG1616(const GLfloat src[4], void *dst) +{ + GLuint *d = (GLuint *) dst; + GLshort r = FLOAT_TO_SHORT(CLAMP(src[RCOMP], -1.0f, 1.0f)); + GLshort g = FLOAT_TO_SHORT(CLAMP(src[GCOMP], -1.0f, 1.0f)); + *d = (r << 16) | (g & 0xffff); +} /** * Return a function that can pack a GLubyte rgba[4] color. @@ -1978,6 +2028,8 @@ _mesa_get_pack_ubyte_rgba_function(gl_format format) table[MESA_FORMAT_XBGR32323232_UINT] = NULL; table[MESA_FORMAT_XBGR32323232_SINT] = NULL; + table[MESA_FORMAT_ABGR2101010] = pack_ubyte_ABGR2101010; + initialized = GL_TRUE; } @@ -2136,6 +2188,11 @@ _mesa_get_pack_float_rgba_function(gl_format format) table[MESA_FORMAT_XBGR32323232_UINT] = NULL; table[MESA_FORMAT_XBGR32323232_SINT] = NULL; + table[MESA_FORMAT_ABGR2101010] = pack_float_ABGR2101010; + + table[MESA_FORMAT_SIGNED_RG88] = pack_float_SIGNED_RG88; + table[MESA_FORMAT_SIGNED_RG1616] = pack_float_SIGNED_RG1616; + initialized = GL_TRUE; } diff --git a/mesalib/src/mesa/main/format_unpack.c b/mesalib/src/mesa/main/format_unpack.c index 0a8b8b183..28a50f31e 100644 --- a/mesalib/src/mesa/main/format_unpack.c +++ b/mesalib/src/mesa/main/format_unpack.c @@ -2268,6 +2268,44 @@ unpack_XBGR32323232_SINT(const void *src, GLfloat dst[][4], GLuint n) } } +static void +unpack_ABGR2101010(const void *src, GLfloat dst[][4], GLuint n) +{ + const GLuint *s = ((const GLuint *) src); + GLuint i; + for (i = 0; i < n; i++) { + dst[i][RCOMP] = ((s[i] >> 0) & 0x3ff) * (1.0F / 1023.0F); + dst[i][GCOMP] = ((s[i] >> 10) & 0x3ff) * (1.0F / 1023.0F); + dst[i][BCOMP] = ((s[i] >> 20) & 0x3ff) * (1.0F / 1023.0F); + dst[i][ACOMP] = ((s[i] >> 30) & 0x03) * (1.0F / 3.0F); + } +} + +static void +unpack_SIGNED_RG88(const void *src, GLfloat dst[][4], GLuint n) +{ + const GLushort *s = ((const GLushort *) src); + GLuint i; + for (i = 0; i < n; i++) { + dst[i][RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s[i] >> 8) ); + dst[i][GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s[i] & 0xff) ); + dst[i][BCOMP] = 0.0F; + dst[i][ACOMP] = 1.0F; + } +} + +static void +unpack_SIGNED_RG1616(const void *src, GLfloat dst[][4], GLuint n) +{ + const GLuint *s = ((const GLuint *) src); + GLuint i; + for (i = 0; i < n; i++) { + dst[i][RCOMP] = SHORT_TO_FLOAT_TEX( (GLshort) (s[i] >> 16) ); + dst[i][GCOMP] = SHORT_TO_FLOAT_TEX( (GLshort) (s[i] & 0xffff) ); + dst[i][BCOMP] = 0.0F; + dst[i][ACOMP] = 1.0F; + } +} /** * Return the unpacker function for the given format. @@ -2481,6 +2519,11 @@ get_unpack_rgba_function(gl_format format) table[MESA_FORMAT_XBGR32323232_UINT] = unpack_XBGR32323232_UINT; table[MESA_FORMAT_XBGR32323232_SINT] = unpack_XBGR32323232_SINT; + table[MESA_FORMAT_ABGR2101010] = unpack_ABGR2101010; + + table[MESA_FORMAT_SIGNED_RG88] = unpack_SIGNED_RG88; + table[MESA_FORMAT_SIGNED_RG1616] = unpack_SIGNED_RG1616; + initialized = GL_TRUE; } @@ -3582,6 +3625,20 @@ unpack_int_rgba_XBGR32323232_UINT(const GLuint *src, GLuint dst[][4], GLuint n) } } +static void +unpack_int_rgba_ABGR2101010(const GLuint *src, GLuint dst[][4], GLuint n) +{ + unsigned int i; + + for (i = 0; i < n; i++) { + GLuint tmp = src[i]; + dst[i][0] = (tmp >> 0) & 0x3ff; + dst[i][1] = (tmp >> 10) & 0x3ff; + dst[i][2] = (tmp >> 20) & 0x3ff; + dst[i][3] = (tmp >> 30) & 0x3; + } +} + void _mesa_unpack_uint_rgba_row(gl_format format, GLuint n, const void *src, GLuint dst[][4]) @@ -3782,6 +3839,10 @@ _mesa_unpack_uint_rgba_row(gl_format format, GLuint n, unpack_int_rgba_XBGR32323232_UINT(src, dst, n); break; + case MESA_FORMAT_ABGR2101010: + unpack_int_rgba_ABGR2101010(src, dst, n); + break; + default: _mesa_problem(NULL, "%s: bad format %s", __FUNCTION__, _mesa_get_format_name(format)); diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index 7e0ec2319..1246c4d92 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -1763,6 +1763,33 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 0, 0, 0, 0, 0, 1, 1, 16 }, + { + MESA_FORMAT_ABGR2101010, + "MESA_FORMAT_ABGR2101010", + GL_RGBA, + GL_UNSIGNED_NORMALIZED, + 10, 10, 10, 2, + 0, 0, 0, 0, 0, + 1, 1, 4 + }, + { + MESA_FORMAT_SIGNED_RG88, + "MESA_FORMAT_SIGNED_RG88", + GL_RG, + GL_SIGNED_NORMALIZED, + 8, 8, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 2 + }, + { + MESA_FORMAT_SIGNED_RG1616, + "MESA_FORMAT_SIGNED_RG1616", + GL_RG, + GL_SIGNED_NORMALIZED, + 16, 16, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 4 + }, }; @@ -2841,6 +2868,21 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 4; return; + case MESA_FORMAT_ABGR2101010: + *datatype = GL_UNSIGNED_INT_2_10_10_10_REV; + *comps = 4; + return; + + case MESA_FORMAT_SIGNED_RG88: + *datatype = GL_BYTE; + *comps = 2; + return; + + case MESA_FORMAT_SIGNED_RG1616: + *datatype = GL_SHORT; + *comps = 2; + return; + case MESA_FORMAT_COUNT: assert(0); return; @@ -3382,6 +3424,18 @@ _mesa_format_matches_format_and_type(gl_format gl_format, case MESA_FORMAT_XBGR32323232_UINT: case MESA_FORMAT_XBGR32323232_SINT: return GL_FALSE; + + case MESA_FORMAT_ABGR2101010: + return format == GL_RGBA && type == GL_UNSIGNED_INT_2_10_10_10_REV && + !swapBytes; + + case MESA_FORMAT_SIGNED_RG88: + return format == GL_RG && type == GL_BYTE && !littleEndian && + !swapBytes; + + case MESA_FORMAT_SIGNED_RG1616: + return format == GL_RG && type == GL_SHORT && !littleEndian && + !swapBytes; } return GL_FALSE; diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 0c91aeaac..a1f0d226a 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -304,6 +304,11 @@ typedef enum MESA_FORMAT_XBGR32323232_UINT, /* ... */ MESA_FORMAT_XBGR32323232_SINT, /* ... */ + MESA_FORMAT_ABGR2101010, + + MESA_FORMAT_SIGNED_RG88, + MESA_FORMAT_SIGNED_RG1616, + MESA_FORMAT_COUNT } gl_format; diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 6e55e9956..b13f9a3db 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -145,6 +145,7 @@ enum value_extra { EXTRA_GLSL_130, EXTRA_EXT_UBO_GS4, EXTRA_EXT_ATOMICS_GS4, + EXTRA_EXT_SHADER_IMAGE_GS4, }; #define NO_EXTRA NULL @@ -344,6 +345,11 @@ static const int extra_ARB_shader_atomic_counters_and_geometry_shader[] = { EXTRA_END }; +static const int extra_ARB_shader_image_load_store_and_geometry_shader[] = { + EXTRA_EXT_SHADER_IMAGE_GS4, + EXTRA_END +}; + EXTRA_EXT(ARB_texture_cube_map); EXTRA_EXT(EXT_texture_array); EXTRA_EXT(NV_fog_distance); @@ -382,6 +388,7 @@ EXTRA_EXT(ARB_texture_multisample); EXTRA_EXT(ARB_texture_gather); EXTRA_EXT(ARB_shader_atomic_counters); EXTRA_EXT(ARB_draw_indirect); +EXTRA_EXT(ARB_shader_image_load_store); static const int extra_ARB_color_buffer_float_or_glcore[] = { @@ -1071,6 +1078,11 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d api_found = (ctx->Extensions.ARB_shader_atomic_counters && _mesa_has_geometry_shaders(ctx)); break; + case EXTRA_EXT_SHADER_IMAGE_GS4: + api_check = GL_TRUE; + api_found = (ctx->Extensions.ARB_shader_image_load_store && + _mesa_has_geometry_shaders(ctx)); + break; case EXTRA_END: break; default: /* *e is a offset into the extension struct */ @@ -1811,6 +1823,64 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) goto invalid_value; v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride; + + /* ARB_shader_image_load_store */ + case GL_IMAGE_BINDING_NAME: { + struct gl_texture_object *t; + + if (!ctx->Extensions.ARB_shader_image_load_store) + goto invalid_enum; + if (index >= ctx->Const.MaxImageUnits) + goto invalid_value; + + t = ctx->ImageUnits[index].TexObj; + v->value_int = (t ? t->Name : 0); + return TYPE_INT; + } + + case GL_IMAGE_BINDING_LEVEL: + if (!ctx->Extensions.ARB_shader_image_load_store) + goto invalid_enum; + if (index >= ctx->Const.MaxImageUnits) + goto invalid_value; + + v->value_int = ctx->ImageUnits[index].Level; + return TYPE_INT; + + case GL_IMAGE_BINDING_LAYERED: + if (!ctx->Extensions.ARB_shader_image_load_store) + goto invalid_enum; + if (index >= ctx->Const.MaxImageUnits) + goto invalid_value; + + v->value_int = ctx->ImageUnits[index].Layered; + return TYPE_INT; + + case GL_IMAGE_BINDING_LAYER: + if (!ctx->Extensions.ARB_shader_image_load_store) + goto invalid_enum; + if (index >= ctx->Const.MaxImageUnits) + goto invalid_value; + + v->value_int = ctx->ImageUnits[index].Layer; + return TYPE_INT; + + case GL_IMAGE_BINDING_ACCESS: + if (!ctx->Extensions.ARB_shader_image_load_store) + goto invalid_enum; + if (index >= ctx->Const.MaxImageUnits) + goto invalid_value; + + v->value_int = ctx->ImageUnits[index].Access; + return TYPE_INT; + + case GL_IMAGE_BINDING_FORMAT: + if (!ctx->Extensions.ARB_shader_image_load_store) + goto invalid_enum; + if (index >= ctx->Const.MaxImageUnits) + goto invalid_value; + + v->value_int = ctx->ImageUnits[index].Format; return TYPE_INT; } diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 7f025a980..6195d630d 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -742,6 +742,15 @@ descriptor=[ # GL_ARB_vertex_attrib_binding [ "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", "CONTEXT_ENUM(Const.MaxVertexAttribRelativeOffset), NO_EXTRA" ], [ "MAX_VERTEX_ATTRIB_BINDINGS", "CONTEXT_ENUM(Const.MaxVertexAttribBindings), NO_EXTRA" ], + +# GL_ARB_shader_image_load_store + [ "MAX_IMAGE_UNITS", "CONTEXT_INT(Const.MaxImageUnits), extra_ARB_shader_image_load_store"], + [ "MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS", "CONTEXT_INT(Const.MaxCombinedImageUnitsAndFragmentOutputs), extra_ARB_shader_image_load_store"], + [ "MAX_IMAGE_SAMPLES", "CONTEXT_INT(Const.MaxImageSamples), extra_ARB_shader_image_load_store"], + [ "MAX_VERTEX_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_VERTEX].MaxImageUniforms), extra_ARB_shader_image_load_store"], + [ "MAX_GEOMETRY_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_GEOMETRY].MaxImageUniforms), extra_ARB_shader_image_load_store_and_geometry_shader"], + [ "MAX_FRAGMENT_IMAGE_UNIFORMS", "CONTEXT_INT(Const.Program[MESA_SHADER_FRAGMENT].MaxImageUniforms), extra_ARB_shader_image_load_store"], + [ "MAX_COMBINED_IMAGE_UNIFORMS", "CONTEXT_INT(Const.MaxCombinedImageUniforms), extra_ARB_shader_image_load_store"], ]}, # Enums restricted to OpenGL Core profile diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index f23cd8118..33df682cf 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1230,6 +1230,9 @@ struct gl_texture_object /** GL_OES_EGL_image_external */ GLint RequiredTextureImageUnits; + + /** GL_ARB_shader_image_load_store */ + GLenum ImageFormatCompatibilityType; }; @@ -2402,6 +2405,32 @@ struct gl_shader */ GLenum OutputType; } Geom; + + /** + * Map from image uniform index to image unit (set by glUniform1i()) + * + * An image uniform index is associated with each image uniform by + * the linker. The image index associated with each uniform is + * stored in the \c gl_uniform_storage::image field. + */ + GLubyte ImageUnits[MAX_IMAGE_UNIFORMS]; + + /** + * Access qualifier specified in the shader for each image uniform + * index. Either \c GL_READ_ONLY, \c GL_WRITE_ONLY or \c + * GL_READ_WRITE. + * + * It may be different, though only more strict than the value of + * \c gl_image_unit::Access for the corresponding image unit. + */ + GLenum ImageAccess[MAX_IMAGE_UNIFORMS]; + + /** + * Number of image uniforms defined in the shader. It specifies + * the number of valid elements in the \c ImageUnits and \c + * ImageAccess arrays above. + */ + GLuint NumImages; }; @@ -3089,9 +3118,13 @@ struct gl_program_constants GLuint MaxUniformBlocks; GLuint MaxCombinedUniformComponents; GLuint MaxTextureImageUnits; + /* GL_ARB_shader_atomic_counters */ GLuint MaxAtomicBuffers; GLuint MaxAtomicCounters; + + /* GL_ARB_shader_image_load_store */ + GLuint MaxImageUniforms; }; @@ -3312,6 +3345,12 @@ struct gl_constants /** GL_ARB_vertex_attrib_binding */ GLint MaxVertexAttribRelativeOffset; GLint MaxVertexAttribBindings; + + /* GL_ARB_shader_image_load_store */ + GLuint MaxImageUnits; + GLuint MaxCombinedImageUnitsAndFragmentOutputs; + GLuint MaxImageSamples; + GLuint MaxCombinedImageUniforms; }; @@ -3359,6 +3398,7 @@ struct gl_extensions GLboolean ARB_seamless_cube_map; GLboolean ARB_shader_atomic_counters; GLboolean ARB_shader_bit_encoding; + GLboolean ARB_shader_image_load_store; GLboolean ARB_shader_stencil_export; GLboolean ARB_shader_texture_lod; GLboolean ARB_shading_language_packing; @@ -3737,6 +3777,11 @@ struct gl_driver_flags * gl_context::AtomicBufferBindings */ GLbitfield NewAtomicBuffer; + + /** + * gl_context::ImageUnits + */ + GLbitfield NewImageUnits; }; struct gl_uniform_buffer_binding @@ -3754,6 +3799,60 @@ struct gl_uniform_buffer_binding }; /** + * ARB_shader_image_load_store image unit. + */ +struct gl_image_unit +{ + /** + * Texture object bound to this unit. + */ + struct gl_texture_object *TexObj; + + /** + * Level of the texture object bound to this unit. + */ + GLuint Level; + + /** + * \c GL_TRUE if the whole level is bound as an array of layers, \c + * GL_FALSE if only some specific layer of the texture is bound. + * \sa Layer + */ + GLboolean Layered; + + /** + * Layer of the texture object bound to this unit, or zero if the + * whole level is bound. + */ + GLuint Layer; + + /** + * Access allowed to this texture image. Either \c GL_READ_ONLY, + * \c GL_WRITE_ONLY or \c GL_READ_WRITE. + */ + GLenum Access; + + /** + * GL internal format that determines the interpretation of the + * image memory when shader image operations are performed through + * this unit. + */ + GLenum Format; + + /** + * Mesa format corresponding to \c Format. + */ + gl_format _ActualFormat; + + /** + * GL_TRUE if the state of this image unit is valid and access from + * the shader is allowed. Otherwise loads from this unit should + * return zero and stores should have no effect. + */ + GLboolean _Valid; +}; + +/** * Binding point for an atomic counter buffer object. */ struct gl_atomic_buffer_binding @@ -3945,6 +4044,11 @@ struct gl_context struct gl_atomic_buffer_binding AtomicBufferBindings[MAX_COMBINED_ATOMIC_BUFFERS]; + /** + * Array of image units for ARB_shader_image_load_store. + */ + struct gl_image_unit ImageUnits[MAX_IMAGE_UNITS]; + /*@}*/ struct gl_meta_state *Meta; /**< for "meta" operations */ diff --git a/mesalib/src/mesa/main/scissor.c b/mesalib/src/mesa/main/scissor.c index 0eddaa6c1..ac86bd591 100644 --- a/mesalib/src/mesa/main/scissor.c +++ b/mesalib/src/mesa/main/scissor.c @@ -79,7 +79,7 @@ _mesa_set_scissor(struct gl_context *ctx, ctx->Scissor.Height = height; if (ctx->Driver.Scissor) - ctx->Driver.Scissor( ctx, x, y, width, height ); + ctx->Driver.Scissor(ctx); } diff --git a/mesalib/src/mesa/main/shaderimage.c b/mesalib/src/mesa/main/shaderimage.c new file mode 100644 index 000000000..80c469366 --- /dev/null +++ b/mesalib/src/mesa/main/shaderimage.c @@ -0,0 +1,488 @@ +/* + * Copyright 2013 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. + * + * Authors: + * Francisco Jerez <currojerez@riseup.net> + */ + +#include <assert.h> + +#include "shaderimage.h" +#include "mtypes.h" +#include "formats.h" +#include "errors.h" +#include "context.h" +#include "texobj.h" +#include "teximage.h" + +/* + * Define endian-invariant aliases for some mesa formats that are + * defined in terms of their channel layout from LSB to MSB in a + * 32-bit word. The actual byte offsets matter here because the user + * is allowed to bit-cast one format into another and get predictable + * results. + */ +#ifdef MESA_BIG_ENDIAN +# define MESA_FORMAT_RGBA_8 MESA_FORMAT_RGBA8888 +# define MESA_FORMAT_RG_16 MESA_FORMAT_RG1616 +# define MESA_FORMAT_RG_8 MESA_FORMAT_RG88 +# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_SIGNED_RGBA8888 +# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_SIGNED_RG1616 +# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_SIGNED_RG88 +#else +# define MESA_FORMAT_RGBA_8 MESA_FORMAT_RGBA8888_REV +# define MESA_FORMAT_RG_16 MESA_FORMAT_GR1616 +# define MESA_FORMAT_RG_8 MESA_FORMAT_GR88 +# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_SIGNED_RGBA8888_REV +# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_SIGNED_GR1616 +# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_SIGNED_RG88_REV +#endif + +static gl_format +get_image_format(GLenum format) +{ + switch (format) { + case GL_RGBA32F: + return MESA_FORMAT_RGBA_FLOAT32; + + case GL_RGBA16F: + return MESA_FORMAT_RGBA_FLOAT16; + + case GL_RG32F: + return MESA_FORMAT_RG_FLOAT32; + + case GL_RG16F: + return MESA_FORMAT_RG_FLOAT16; + + case GL_R11F_G11F_B10F: + return MESA_FORMAT_R11_G11_B10_FLOAT; + + case GL_R32F: + return MESA_FORMAT_R_FLOAT32; + + case GL_R16F: + return MESA_FORMAT_R_FLOAT16; + + case GL_RGBA32UI: + return MESA_FORMAT_RGBA_UINT32; + + case GL_RGBA16UI: + return MESA_FORMAT_RGBA_UINT16; + + case GL_RGB10_A2UI: + return MESA_FORMAT_ABGR2101010_UINT; + + case GL_RGBA8UI: + return MESA_FORMAT_RGBA_UINT8; + + case GL_RG32UI: + return MESA_FORMAT_RG_UINT32; + + case GL_RG16UI: + return MESA_FORMAT_RG_UINT16; + + case GL_RG8UI: + return MESA_FORMAT_RG_UINT8; + + case GL_R32UI: + return MESA_FORMAT_R_UINT32; + + case GL_R16UI: + return MESA_FORMAT_R_UINT16; + + case GL_R8UI: + return MESA_FORMAT_R_UINT8; + + case GL_RGBA32I: + return MESA_FORMAT_RGBA_INT32; + + case GL_RGBA16I: + return MESA_FORMAT_RGBA_INT16; + + case GL_RGBA8I: + return MESA_FORMAT_RGBA_INT8; + + case GL_RG32I: + return MESA_FORMAT_RG_INT32; + + case GL_RG16I: + return MESA_FORMAT_RG_INT16; + + case GL_RG8I: + return MESA_FORMAT_RG_INT8; + + case GL_R32I: + return MESA_FORMAT_R_INT32; + + case GL_R16I: + return MESA_FORMAT_R_INT16; + + case GL_R8I: + return MESA_FORMAT_R_INT8; + + case GL_RGBA16: + return MESA_FORMAT_RGBA_16; + + case GL_RGB10_A2: + return MESA_FORMAT_ABGR2101010; + + case GL_RGBA8: + return MESA_FORMAT_RGBA_8; + + case GL_RG16: + return MESA_FORMAT_RG_16; + + case GL_RG8: + return MESA_FORMAT_RG_8; + + case GL_R16: + return MESA_FORMAT_R16; + + case GL_R8: + return MESA_FORMAT_R8; + + case GL_RGBA16_SNORM: + return MESA_FORMAT_SIGNED_RGBA_16; + + case GL_RGBA8_SNORM: + return MESA_FORMAT_SIGNED_RGBA_8; + + case GL_RG16_SNORM: + return MESA_FORMAT_SIGNED_RG_16; + + case GL_RG8_SNORM: + return MESA_FORMAT_SIGNED_RG_8; + + case GL_R16_SNORM: + return MESA_FORMAT_SIGNED_R16; + + case GL_R8_SNORM: + return MESA_FORMAT_SIGNED_R8; + + default: + return MESA_FORMAT_NONE; + } +} + +enum image_format_class +{ + /** Not a valid image format. */ + IMAGE_FORMAT_CLASS_NONE = 0, + + /** Classes of image formats you can cast into each other. */ + /** \{ */ + IMAGE_FORMAT_CLASS_1X8, + IMAGE_FORMAT_CLASS_1X16, + IMAGE_FORMAT_CLASS_1X32, + IMAGE_FORMAT_CLASS_2X8, + IMAGE_FORMAT_CLASS_2X16, + IMAGE_FORMAT_CLASS_2X32, + IMAGE_FORMAT_CLASS_10_11_11, + IMAGE_FORMAT_CLASS_4X8, + IMAGE_FORMAT_CLASS_4X16, + IMAGE_FORMAT_CLASS_4X32, + IMAGE_FORMAT_CLASS_2_10_10_10 + /** \} */ +}; + +static enum image_format_class +get_image_format_class(gl_format format) +{ + switch (format) { + case MESA_FORMAT_RGBA_FLOAT32: + return IMAGE_FORMAT_CLASS_4X32; + + case MESA_FORMAT_RGBA_FLOAT16: + return IMAGE_FORMAT_CLASS_4X16; + + case MESA_FORMAT_RG_FLOAT32: + return IMAGE_FORMAT_CLASS_2X32; + + case MESA_FORMAT_RG_FLOAT16: + return IMAGE_FORMAT_CLASS_2X16; + + case MESA_FORMAT_R11_G11_B10_FLOAT: + return IMAGE_FORMAT_CLASS_10_11_11; + + case MESA_FORMAT_R_FLOAT32: + return IMAGE_FORMAT_CLASS_1X32; + + case MESA_FORMAT_R_FLOAT16: + return IMAGE_FORMAT_CLASS_1X16; + + case MESA_FORMAT_RGBA_UINT32: + return IMAGE_FORMAT_CLASS_4X32; + + case MESA_FORMAT_RGBA_UINT16: + return IMAGE_FORMAT_CLASS_4X16; + + case MESA_FORMAT_ABGR2101010_UINT: + return IMAGE_FORMAT_CLASS_2_10_10_10; + + case MESA_FORMAT_RGBA_UINT8: + return IMAGE_FORMAT_CLASS_4X8; + + case MESA_FORMAT_RG_UINT32: + return IMAGE_FORMAT_CLASS_2X32; + + case MESA_FORMAT_RG_UINT16: + return IMAGE_FORMAT_CLASS_2X16; + + case MESA_FORMAT_RG_UINT8: + return IMAGE_FORMAT_CLASS_2X8; + + case MESA_FORMAT_R_UINT32: + return IMAGE_FORMAT_CLASS_1X32; + + case MESA_FORMAT_R_UINT16: + return IMAGE_FORMAT_CLASS_1X16; + + case MESA_FORMAT_R_UINT8: + return IMAGE_FORMAT_CLASS_1X8; + + case MESA_FORMAT_RGBA_INT32: + return IMAGE_FORMAT_CLASS_4X32; + + case MESA_FORMAT_RGBA_INT16: + return IMAGE_FORMAT_CLASS_4X16; + + case MESA_FORMAT_RGBA_INT8: + return IMAGE_FORMAT_CLASS_4X8; + + case MESA_FORMAT_RG_INT32: + return IMAGE_FORMAT_CLASS_2X32; + + case MESA_FORMAT_RG_INT16: + return IMAGE_FORMAT_CLASS_2X16; + + case MESA_FORMAT_RG_INT8: + return IMAGE_FORMAT_CLASS_2X8; + + case MESA_FORMAT_R_INT32: + return IMAGE_FORMAT_CLASS_1X32; + + case MESA_FORMAT_R_INT16: + return IMAGE_FORMAT_CLASS_1X16; + + case MESA_FORMAT_R_INT8: + return IMAGE_FORMAT_CLASS_1X8; + + case MESA_FORMAT_RGBA_16: + return IMAGE_FORMAT_CLASS_4X16; + + case MESA_FORMAT_ABGR2101010: + return IMAGE_FORMAT_CLASS_2_10_10_10; + + case MESA_FORMAT_RGBA_8: + return IMAGE_FORMAT_CLASS_4X8; + + case MESA_FORMAT_RG_16: + return IMAGE_FORMAT_CLASS_2X16; + + case MESA_FORMAT_RG_8: + return IMAGE_FORMAT_CLASS_2X8; + + case MESA_FORMAT_R16: + return IMAGE_FORMAT_CLASS_1X16; + + case MESA_FORMAT_R8: + return IMAGE_FORMAT_CLASS_1X8; + + case MESA_FORMAT_SIGNED_RGBA_16: + return IMAGE_FORMAT_CLASS_4X16; + + case MESA_FORMAT_SIGNED_RGBA_8: + return IMAGE_FORMAT_CLASS_4X8; + + case MESA_FORMAT_SIGNED_RG_16: + return IMAGE_FORMAT_CLASS_2X16; + + case MESA_FORMAT_SIGNED_RG_8: + return IMAGE_FORMAT_CLASS_2X8; + + case MESA_FORMAT_SIGNED_R16: + return IMAGE_FORMAT_CLASS_1X16; + + case MESA_FORMAT_SIGNED_R8: + return IMAGE_FORMAT_CLASS_1X8; + + default: + return IMAGE_FORMAT_CLASS_NONE; + } +} + +static GLboolean +validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u) +{ + struct gl_texture_object *t = u->TexObj; + struct gl_texture_image *img; + + if (!t || u->Level < t->BaseLevel || + u->Level > t->_MaxLevel) + return GL_FALSE; + + _mesa_test_texobj_completeness(ctx, t); + + if ((u->Level == t->BaseLevel && !t->_BaseComplete) || + (u->Level != t->BaseLevel && !t->_MipmapComplete)) + return GL_FALSE; + + if (_mesa_tex_target_is_layered(t->Target) && + u->Layer >= _mesa_get_texture_layers(t, u->Level)) + return GL_FALSE; + + if (t->Target == GL_TEXTURE_CUBE_MAP) + img = t->Image[u->Layer][u->Level]; + else + img = t->Image[0][u->Level]; + + if (!img || img->Border || + get_image_format_class(img->TexFormat) == IMAGE_FORMAT_CLASS_NONE || + img->NumSamples > ctx->Const.MaxImageSamples) + return GL_FALSE; + + switch (t->ImageFormatCompatibilityType) { + case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE: + if (_mesa_get_format_bytes(img->TexFormat) != + _mesa_get_format_bytes(u->_ActualFormat)) + return GL_FALSE; + break; + + case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS: + if (get_image_format_class(img->TexFormat) != + get_image_format_class(u->_ActualFormat)) + return GL_FALSE; + break; + + default: + assert(!"Unexpected image format compatibility type"); + } + + return GL_TRUE; +} + +void +_mesa_validate_image_units(struct gl_context *ctx) +{ + int i; + + for (i = 0; i < ctx->Const.MaxImageUnits; ++i) { + struct gl_image_unit *u = &ctx->ImageUnits[i]; + u->_Valid = validate_image_unit(ctx, u); + } +} + +static GLboolean +validate_bind_image_texture(struct gl_context *ctx, GLuint unit, + GLuint texture, GLint level, GLboolean layered, + GLint layer, GLenum access, GLenum format) +{ + assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS); + + if (unit >= ctx->Const.MaxImageUnits) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)"); + return GL_FALSE; + } + + if (level < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)"); + return GL_FALSE; + } + + if (layer < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)"); + return GL_FALSE; + } + + if (access != GL_READ_ONLY && + access != GL_WRITE_ONLY && + access != GL_READ_WRITE) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)"); + return GL_FALSE; + } + + if (!get_image_format(format)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)"); + return GL_FALSE; + } + + return GL_TRUE; +} + +void GLAPIENTRY +_mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, + GLboolean layered, GLint layer, GLenum access, + GLenum format) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_object *t = NULL; + struct gl_image_unit *u; + + if (!validate_bind_image_texture(ctx, unit, texture, level, + layered, layer, access, format)) + return; + + u = &ctx->ImageUnits[unit]; + + FLUSH_VERTICES(ctx, 0); + ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; + + if (texture) { + t = _mesa_lookup_texture(ctx, texture); + if (!t) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)"); + return; + } + + _mesa_reference_texobj(&u->TexObj, t); + u->Level = level; + u->Access = access; + u->Format = format; + u->_ActualFormat = get_image_format(format); + + if (_mesa_tex_target_is_layered(t->Target)) { + u->Layered = layered; + u->Layer = (layered ? 0 : layer); + } else { + u->Layered = GL_FALSE; + u->Layer = 0; + } + + } else { + _mesa_reference_texobj(&u->TexObj, NULL); + } + + u->_Valid = validate_image_unit(ctx, u); + + if (ctx->Driver.BindImageTexture) + ctx->Driver.BindImageTexture(ctx, u, t, level, layered, + layer, access, format); +} + +void GLAPIENTRY +_mesa_MemoryBarrier(GLbitfield barriers) +{ + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Driver.MemoryBarrier) + ctx->Driver.MemoryBarrier(ctx, barriers); +} diff --git a/mesalib/src/mesa/main/shaderimage.h b/mesalib/src/mesa/main/shaderimage.h new file mode 100644 index 000000000..aaecc5d29 --- /dev/null +++ b/mesalib/src/mesa/main/shaderimage.h @@ -0,0 +1,51 @@ +/* + * Copyright 2013 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. + * + * Authors: + * Francisco Jerez <currojerez@riseup.net> + */ + +#ifndef SHADERIMAGE_H +#define SHADERIMAGE_H + +#include "glheader.h" + +struct gl_context; + +/** + * Recalculate the \c _Valid flag of a context's shader image units. + * + * To be called when the state of any texture bound to an image unit + * changes. + */ +void +_mesa_validate_image_units(struct gl_context *ctx); + +void GLAPIENTRY +_mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, + GLboolean layered, GLint layer, GLenum access, + GLenum format); + +void GLAPIENTRY +_mesa_MemoryBarrier(GLbitfield barriers); + +#endif diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index e71d0c411..47ad30605 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -263,6 +263,43 @@ _mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats) else { n += 3; } + + /* The ES and desktop GL specs diverge here. + * + * In desktop OpenGL, the driver can perform online compression of + * uncompressed texture data. GL_NUM_COMPRESSED_TEXTURE_FORMATS and + * GL_COMPRESSED_TEXTURE_FORMATS give the application a list of + * formats that it could ask the driver to compress with some + * expectation of quality. The GL_ARB_texture_compression spec + * calls this "suitable for general-purpose usage." As noted + * above, this means GL_COMPRESSED_RGBA_S3TC_DXT1_EXT is not + * included in the list. + * + * In OpenGL ES, the driver never performs compression. + * GL_NUM_COMPRESSED_TEXTURE_FORMATS and + * GL_COMPRESSED_TEXTURE_FORMATS give the application a list of + * formats that the driver can receive from the application. It + * is the *complete* list of formats. The + * GL_EXT_texture_compression_s3tc spec says: + * + * "New State for OpenGL ES 2.0.25 and 3.0.2 Specifications + * + * The queries for NUM_COMPRESSED_TEXTURE_FORMATS and + * COMPRESSED_TEXTURE_FORMATS include + * COMPRESSED_RGB_S3TC_DXT1_EXT, + * COMPRESSED_RGBA_S3TC_DXT1_EXT, + * COMPRESSED_RGBA_S3TC_DXT3_EXT, and + * COMPRESSED_RGBA_S3TC_DXT5_EXT." + * + * Note that the addition is only to the OpenGL ES specification! + */ + if (_mesa_is_gles(ctx)) { + if (formats) { + formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + } else { + n += 1; + } + } } /* The GL_OES_compressed_ETC1_RGB8_texture spec says: diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 9c3f1e86e..8aac54e9d 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -1088,6 +1088,93 @@ _mesa_get_texture_dimensions(GLenum target) /** + * Check if a texture target can have more than one layer. + */ +GLboolean +_mesa_tex_target_is_layered(GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_PROXY_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_PROXY_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_BUFFER: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + case GL_TEXTURE_EXTERNAL_OES: + return GL_FALSE; + + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + case GL_PROXY_TEXTURE_CUBE_MAP: + case GL_TEXTURE_1D_ARRAY: + case GL_PROXY_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D_ARRAY: + case GL_PROXY_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: + return GL_TRUE; + + default: + assert(!"Invalid texture target."); + return GL_FALSE; + } +} + + +/** + * Return the number of layers present in the given level of an array, + * cubemap or 3D texture. If the texture is not layered return zero. + */ +GLuint +_mesa_get_texture_layers(const struct gl_texture_object *texObj, GLint level) +{ + assert(level >= 0 && level < MAX_TEXTURE_LEVELS); + + switch (texObj->Target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_BUFFER: + case GL_TEXTURE_EXTERNAL_OES: + return 0; + + case GL_TEXTURE_CUBE_MAP: + return 6; + + case GL_TEXTURE_1D_ARRAY: { + struct gl_texture_image *img = texObj->Image[0][level]; + return img ? img->Height : 0; + } + + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_CUBE_MAP_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { + struct gl_texture_image *img = texObj->Image[0][level]; + return img ? img->Depth : 0; + } + + default: + assert(!"Invalid texture target."); + return 0; + } +} + + +/** * Return the maximum number of mipmap levels for the given target * and the dimensions. * The dimensions are expected not to include the border. diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 0b5786340..80a0a57b5 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -138,6 +138,12 @@ _mesa_tex_target_to_face(GLenum target); extern GLint _mesa_get_texture_dimensions(GLenum target); +extern GLboolean +_mesa_tex_target_is_layered(GLenum target); + +extern GLuint +_mesa_get_texture_layers(const struct gl_texture_object *texObj, GLint level); + extern GLsizei _mesa_get_tex_max_num_levels(GLenum target, GLsizei width, GLsizei height, GLsizei depth); diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index d6510fefd..3c64c4376 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -157,6 +157,7 @@ _mesa_initialize_texture_object( struct gl_context *ctx, obj->Sampler.sRGBDecode = GL_DECODE_EXT; obj->BufferObjectFormat = GL_R8; obj->_BufferObjectFormat = MESA_FORMAT_R8; + obj->ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE; } @@ -1099,6 +1100,25 @@ unbind_texobj_from_texunits(struct gl_context *ctx, /** + * Check if the given texture object is bound to any shader image unit + * and unbind it if that's the case. + */ +static void +unbind_texobj_from_imgunits(struct gl_context *ctx, + struct gl_texture_object *texObj) +{ + int i; + + for (i = 0; i < ctx->Const.MaxImageUnits; i++) { + struct gl_image_unit *unit = &ctx->ImageUnits[i]; + + if (texObj == unit->TexObj) + _mesa_reference_texobj(&unit->TexObj, NULL); + } +} + + +/** * Delete named textures. * * \param n number of textures to be deleted. @@ -1145,6 +1165,12 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) */ unbind_texobj_from_texunits(ctx, delObj); + /* Check if this texture is currently bound to any shader + * image unit. If so, unbind it. + * See section 3.9.X of GL_ARB_shader_image_load_store. + */ + unbind_texobj_from_imgunits(ctx, delObj); + _mesa_unlock_texture(ctx, delObj); ctx->NewState |= _NEW_TEXTURE; diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 94e498d20..7c59d119f 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -1808,6 +1808,12 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) *params = obj->Sampler.sRGBDecode; break; + case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE: + if (!ctx->Extensions.ARB_shader_image_load_store) + goto invalid_pname; + *params = obj->ImageFormatCompatibilityType; + break; + default: goto invalid_pname; } diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c index ad80dcfaa..7720965a8 100644 --- a/mesalib/src/mesa/main/texstate.c +++ b/mesalib/src/mesa/main/texstate.c @@ -35,6 +35,7 @@ #include "context.h" #include "enums.h" #include "macros.h" +#include "shaderimage.h" #include "texobj.h" #include "teximage.h" #include "texstate.h" @@ -674,6 +675,8 @@ update_texture_state( struct gl_context *ctx ) if (!fprog || !vprog) update_texgen(ctx); + + _mesa_validate_image_units(ctx); } diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 5adbd5dc9..8eaf43a6a 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -2191,6 +2191,7 @@ _mesa_texstore_snorm88(TEXSTORE_PARAMS) const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL88 || + dstFormat == MESA_FORMAT_SIGNED_RG88 || dstFormat == MESA_FORMAT_SIGNED_RG88_REV); ASSERT(_mesa_get_format_bytes(dstFormat) == 2); @@ -2210,13 +2211,27 @@ _mesa_texstore_snorm88(TEXSTORE_PARAMS) for (img = 0; img < srcDepth; img++) { GLbyte *dstRow = (GLbyte *) dstSlices[img]; for (row = 0; row < srcHeight; row++) { - GLbyte *dst = dstRow; - for (col = 0; col < srcWidth; col++) { - dst[0] = FLOAT_TO_BYTE_TEX(src[0]); - dst[1] = FLOAT_TO_BYTE_TEX(src[1]); - src += 2; - dst += 2; + GLushort *dst = (GLushort *) dstRow; + + if (dstFormat == MESA_FORMAT_SIGNED_AL88 || + dstFormat == MESA_FORMAT_SIGNED_RG88_REV) { + for (col = 0; col < srcWidth; col++) { + GLubyte l = FLOAT_TO_BYTE_TEX(src[0]); + GLubyte a = FLOAT_TO_BYTE_TEX(src[1]); + + dst[col] = PACK_COLOR_88_REV(l, a); + src += 2; + } + } else { + for (col = 0; col < srcWidth; col++) { + GLubyte l = FLOAT_TO_BYTE_TEX(src[0]); + GLubyte a = FLOAT_TO_BYTE_TEX(src[1]); + + dst[col] = PACK_COLOR_88(l, a); + src += 2; + } } + dstRow += dstRowStride; } } @@ -2278,6 +2293,7 @@ _mesa_texstore_snorm1616(TEXSTORE_PARAMS) const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); ASSERT(dstFormat == MESA_FORMAT_SIGNED_AL1616 || + dstFormat == MESA_FORMAT_SIGNED_RG1616 || dstFormat == MESA_FORMAT_SIGNED_GR1616); ASSERT(_mesa_get_format_bytes(dstFormat) == 4); @@ -2297,17 +2313,29 @@ _mesa_texstore_snorm1616(TEXSTORE_PARAMS) for (img = 0; img < srcDepth; img++) { GLubyte *dstRow = dstSlices[img]; for (row = 0; row < srcHeight; row++) { - GLshort *dst = (GLshort *) dstRow; - for (col = 0; col < srcWidth; col++) { - GLushort l, a; + GLuint *dst = (GLuint *) dstRow; - UNCLAMPED_FLOAT_TO_SHORT(l, src[0]); - UNCLAMPED_FLOAT_TO_SHORT(a, src[1]); - dst[0] = l; - dst[1] = a; - src += 2; - dst += 2; + if (dstFormat == MESA_FORMAT_SIGNED_AL1616 || + dstFormat == MESA_FORMAT_SIGNED_GR1616) { + for (col = 0; col < srcWidth; col++) { + GLushort l, a; + + UNCLAMPED_FLOAT_TO_SHORT(l, src[0]); + UNCLAMPED_FLOAT_TO_SHORT(a, src[1]); + dst[col] = PACK_COLOR_1616_REV(l, a); + src += 2; + } + } else { + for (col = 0; col < srcWidth; col++) { + GLushort l, a; + + UNCLAMPED_FLOAT_TO_SHORT(l, src[0]); + UNCLAMPED_FLOAT_TO_SHORT(a, src[1]); + dst[col] = PACK_COLOR_1616_REV(l, a); + src += 2; + } } + dstRow += dstRowStride; } } @@ -3559,6 +3587,50 @@ _mesa_texstore_abgr2101010_uint(TEXSTORE_PARAMS) } static GLboolean +_mesa_texstore_abgr2101010(TEXSTORE_PARAMS) +{ + const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); + + ASSERT(dstFormat == MESA_FORMAT_ABGR2101010); + ASSERT(_mesa_get_format_bytes(dstFormat) == 4); + + { + /* general path */ + const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, + baseInternalFormat, + baseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking, + ctx->_ImageTransferState); + const GLfloat *src = tempImage; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstSlices[img]; + + for (row = 0; row < srcHeight; row++) { + GLuint *dstUI = (GLuint *) dstRow; + for (col = 0; col < srcWidth; col++) { + GLushort a,r,g,b; + + UNCLAMPED_FLOAT_TO_USHORT(a, src[ACOMP]); + UNCLAMPED_FLOAT_TO_USHORT(r, src[RCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(g, src[GCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(b, src[BCOMP]); + dstUI[col] = PACK_COLOR_2101010_US(a, b, g, r); + src += 4; + } + dstRow += dstRowStride; + } + } + free((void *) tempImage); + } + return GL_TRUE; +} + +static GLboolean _mesa_texstore_null(TEXSTORE_PARAMS) { (void) ctx; (void) dims; @@ -3782,6 +3854,11 @@ _mesa_get_texstore_func(gl_format format) table[MESA_FORMAT_XBGR32323232_UINT] = _mesa_texstore_rgba_uint32; table[MESA_FORMAT_XBGR32323232_SINT] = _mesa_texstore_rgba_int32; + table[MESA_FORMAT_ABGR2101010] = _mesa_texstore_abgr2101010; + + table[MESA_FORMAT_SIGNED_RG88] = _mesa_texstore_snorm88; + table[MESA_FORMAT_SIGNED_RG1616] = _mesa_texstore_snorm1616; + initialized = GL_TRUE; } diff --git a/mesalib/src/mesa/main/viewport.c b/mesalib/src/mesa/main/viewport.c index 91578ba9d..3aaab2d46 100644 --- a/mesalib/src/mesa/main/viewport.c +++ b/mesalib/src/mesa/main/viewport.c @@ -99,7 +99,7 @@ _mesa_set_viewport(struct gl_context *ctx, GLint x, GLint y, /* Many drivers will use this call to check for window size changes * and reallocate the z/stencil/accum/etc buffers if needed. */ - ctx->Driver.Viewport(ctx, x, y, width, height); + ctx->Driver.Viewport(ctx); } } @@ -143,7 +143,7 @@ _mesa_DepthRange(GLclampd nearval, GLclampd farval) #endif if (ctx->Driver.DepthRange) { - ctx->Driver.DepthRange(ctx, nearval, farval); + ctx->Driver.DepthRange(ctx); } } |