diff options
Diffstat (limited to 'mesalib/src/mesa')
-rw-r--r-- | mesalib/src/mesa/Makefile | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/drivers/common/meta.c | 72 | ||||
-rw-r--r-- | mesalib/src/mesa/drivers/windows/gdi/mesa.def | 15 | ||||
-rw-r--r-- | mesalib/src/mesa/main/shaderobj.c | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/program/hash_table.c | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/program/hash_table.h | 17 | ||||
-rw-r--r-- | mesalib/src/mesa/sources.mak | 1 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_atom.c | 27 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_atom.h | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_atom_array.c | 588 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_cb_drawpixels.c | 13 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_context.h | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_draw.c | 573 | ||||
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_draw.h | 7 |
14 files changed, 722 insertions, 609 deletions
diff --git a/mesalib/src/mesa/Makefile b/mesalib/src/mesa/Makefile index 845b524e6..b0b461fdd 100644 --- a/mesalib/src/mesa/Makefile +++ b/mesalib/src/mesa/Makefile @@ -135,7 +135,7 @@ asm_subdirs: ###################################################################### # Dependency generation -depend: $(ALL_FILES) +depend: $(ALL_FILES) main/git_sha1.h @ echo "running $(MKDEP)" @ touch depend @$(MKDEP) $(MKDEP_OPTIONS) $(MESA_CPPFLAGS) \ diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 8d7e90126..be7141a58 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -319,6 +319,10 @@ struct gl_meta_state struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */ }; +static void meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit); +static void cleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex); +static void meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear); + static GLuint compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB *source) { @@ -335,12 +339,16 @@ compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB return shader; _mesa_GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); - if (size == 0) + if (size == 0) { + _mesa_DeleteObjectARB(shader); return 0; + } info = malloc(size); - if (!info) + if (!info) { + _mesa_DeleteObjectARB(shader); return 0; + } _mesa_GetProgramInfoLog(shader, size, NULL, info); _mesa_problem(ctx, @@ -349,6 +357,7 @@ compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB info, source); free(info); + _mesa_DeleteObjectARB(shader); return 0; } @@ -401,10 +410,15 @@ _mesa_meta_init(struct gl_context *ctx) void _mesa_meta_free(struct gl_context *ctx) { - /* Note: Any textures, VBOs, etc, that we allocate should get - * freed by the normal context destruction code. But this would be - * the place to free other meta data someday. - */ + GET_CURRENT_CONTEXT(old_context); + _mesa_make_current(ctx, NULL, NULL); + meta_glsl_blit_cleanup(ctx, &ctx->Meta->Blit); + meta_glsl_clear_cleanup(ctx, &ctx->Meta->Clear); + cleanup_temp_texture(ctx, &ctx->Meta->TempTex); + if (old_context) + _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer); + else + _mesa_make_current(NULL, NULL, NULL); free(ctx->Meta); ctx->Meta = NULL; } @@ -1068,6 +1082,15 @@ init_temp_texture(struct gl_context *ctx, struct temp_texture *tex) _mesa_GenTextures(1, &tex->TexObj); } +static void +cleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex) +{ + if (!tex->TexObj) + return; + _mesa_DeleteTextures(1, &tex->TexObj); + tex->TexObj = 0; +} + /** * Return pointer to temp_texture info for non-bitmap ops. @@ -1604,6 +1627,21 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx, } } +static void +meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit) +{ + if (blit->ArrayObj) { + _mesa_DeleteVertexArraysAPPLE(1, &blit->ArrayObj); + blit->ArrayObj = 0; + _mesa_DeleteBuffersARB(1, &blit->VBO); + blit->VBO = 0; + } + if (blit->DepthFP) { + _mesa_DeletePrograms(1, &blit->DepthFP); + blit->DepthFP = 0; + } +} + /** * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. @@ -1786,7 +1824,9 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) clear->ShaderProg = _mesa_CreateProgramObjectARB(); _mesa_AttachShader(clear->ShaderProg, fs); + _mesa_DeleteObjectARB(fs); _mesa_AttachShader(clear->ShaderProg, vs); + _mesa_DeleteObjectARB(vs); _mesa_BindAttribLocationARB(clear->ShaderProg, 0, "position"); _mesa_LinkProgramARB(clear->ShaderProg); @@ -1799,7 +1839,9 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) clear->IntegerShaderProg = _mesa_CreateProgramObjectARB(); _mesa_AttachShader(clear->IntegerShaderProg, fs); + _mesa_DeleteObjectARB(fs); _mesa_AttachShader(clear->IntegerShaderProg, vs); + _mesa_DeleteObjectARB(vs); _mesa_BindAttribLocationARB(clear->IntegerShaderProg, 0, "position"); /* Note that user-defined out attributes get automatically assigned @@ -1814,6 +1856,24 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) } } +static void +meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear) +{ + if (clear->ArrayObj == 0) + return; + _mesa_DeleteVertexArraysAPPLE(1, &clear->ArrayObj); + clear->ArrayObj = 0; + _mesa_DeleteBuffersARB(1, &clear->VBO); + clear->VBO = 0; + _mesa_DeleteObjectARB(clear->ShaderProg); + clear->ShaderProg = 0; + + if (clear->IntegerShaderProg) { + _mesa_DeleteObjectARB(clear->IntegerShaderProg); + clear->IntegerShaderProg = 0; + } +} + /** * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. */ diff --git a/mesalib/src/mesa/drivers/windows/gdi/mesa.def b/mesalib/src/mesa/drivers/windows/gdi/mesa.def index d5c98801d..fec7bbac0 100644 --- a/mesalib/src/mesa/drivers/windows/gdi/mesa.def +++ b/mesalib/src/mesa/drivers/windows/gdi/mesa.def @@ -556,21 +556,6 @@ EXPORTS glFogCoorddvEXT glFogCoordPointerEXT glBlendFuncSeparateEXT - glFlushVertexArrayRangeNV - glVertexArrayRangeNV - glCombinerParameterfvNV - glCombinerParameterfNV - glCombinerParameterivNV - glCombinerParameteriNV - glCombinerInputNV - glCombinerOutputNV - glFinalCombinerInputNV - glGetCombinerInputParameterfvNV - glGetCombinerInputParameterivNV - glGetCombinerOutputParameterfvNV - glGetCombinerOutputParameterivNV - glGetFinalCombinerInputParameterfvNV - glGetFinalCombinerInputParameterivNV glResizeBuffersMESA glWindowPos2dMESA glWindowPos2dvMESA diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index 7eb6f0bda..16800ae5e 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -278,7 +278,9 @@ _mesa_clear_shader_program_data(struct gl_context *ctx, struct gl_shader_program *shProg) { if (shProg->UniformStorage) { - _mesa_uniform_detach_all_driver_storage(shProg->UniformStorage); + unsigned i; + for (i = 0; i < shProg->NumUserUniformStorage; ++i) + _mesa_uniform_detach_all_driver_storage(&shProg->UniformStorage[i]); ralloc_free(shProg->UniformStorage); shProg->NumUserUniformStorage = 0; shProg->UniformStorage = NULL; diff --git a/mesalib/src/mesa/program/hash_table.c b/mesalib/src/mesa/program/hash_table.c index dc8563a33..7dabadc50 100644 --- a/mesalib/src/mesa/program/hash_table.c +++ b/mesalib/src/mesa/program/hash_table.c @@ -149,7 +149,7 @@ hash_table_insert(struct hash_table *ht, void *data, const void *key) insert_at_head(& ht->buckets[bucket], & node->link); } -void +bool hash_table_replace(struct hash_table *ht, void *data, const void *key) { const unsigned hash_value = (*ht->hash)(key); @@ -162,7 +162,7 @@ hash_table_replace(struct hash_table *ht, void *data, const void *key) if ((*ht->compare)(hn->key, key) == 0) { hn->data = data; - return; + return true; } } @@ -172,6 +172,7 @@ hash_table_replace(struct hash_table *ht, void *data, const void *key) hn->key = key; insert_at_head(& ht->buckets[bucket], & hn->link); + return false; } void diff --git a/mesalib/src/mesa/program/hash_table.h b/mesalib/src/mesa/program/hash_table.h index bcf65df7d..e95fc4982 100644 --- a/mesalib/src/mesa/program/hash_table.h +++ b/mesalib/src/mesa/program/hash_table.h @@ -32,6 +32,7 @@ #define HASH_TABLE_H #include <string.h> +#include <stdbool.h> #include <stdlib.h> #include <stdint.h> #include <limits.h> @@ -114,6 +115,10 @@ extern void hash_table_insert(struct hash_table *ht, void *data, /** * Add an element to a hash table with replacement * + * \return + * 1 if it did replace the the value (in which case the old key is kept), 0 if + * it did not replace the value (in which case the new key is kept). + * * \warning * If \c key is already in the hash table, \c data will \b replace the most * recently inserted \c data (see the warning in \c hash_table_insert) for @@ -121,7 +126,7 @@ extern void hash_table_insert(struct hash_table *ht, void *data, * * \sa hash_table_insert */ -extern void hash_table_replace(struct hash_table *ht, void *data, +extern bool hash_table_replace(struct hash_table *ht, void *data, const void *key); /** @@ -219,6 +224,7 @@ public: */ void clear() { + hash_table_call_foreach(this->ht, delete_key, NULL); hash_table_clear(this->ht); } @@ -258,9 +264,12 @@ public: * because UINT_MAX+1 = 0. */ assert(value != UINT_MAX); - hash_table_replace(this->ht, - (void *) (intptr_t) (value + 1), - strdup(key)); + char *dup_key = strdup(key); + bool result = hash_table_replace(this->ht, + (void *) (intptr_t) (value + 1), + dup_key); + if (result) + free(dup_key); } private: diff --git a/mesalib/src/mesa/sources.mak b/mesalib/src/mesa/sources.mak index 608aa79ab..16b1c39c0 100644 --- a/mesalib/src/mesa/sources.mak +++ b/mesalib/src/mesa/sources.mak @@ -198,6 +198,7 @@ VBO_FILES = \ STATETRACKER_FILES = \ $(SRCDIR)/state_tracker/st_atom.c \ + $(SRCDIR)/state_tracker/st_atom_array.c \ $(SRCDIR)/state_tracker/st_atom_blend.c \ $(SRCDIR)/state_tracker/st_atom_clip.c \ $(SRCDIR)/state_tracker/st_atom_constbuf.c \ diff --git a/mesalib/src/mesa/state_tracker/st_atom.c b/mesalib/src/mesa/state_tracker/st_atom.c index d9cd4aab4..e6fc114f1 100644 --- a/mesalib/src/mesa/state_tracker/st_atom.c +++ b/mesalib/src/mesa/state_tracker/st_atom.c @@ -63,7 +63,10 @@ static const struct st_tracked_state *atoms[] = &st_update_vs_constants, &st_update_gs_constants, &st_update_fs_constants, - &st_update_pixel_transfer + &st_update_pixel_transfer, + + /* this must be done after the vertex program update */ + &st_update_array }; @@ -122,6 +125,22 @@ static void check_program_state( struct st_context *st ) st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; } +static void check_attrib_edgeflag(struct st_context *st) +{ + const struct gl_client_array **arrays = st->ctx->Array._DrawArrays; + GLboolean vertDataEdgeFlags; + + if (!arrays) + return; + + vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && + arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; + if (vertDataEdgeFlags != st->vertdata_edgeflags) { + st->vertdata_edgeflags = vertDataEdgeFlags; + st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; + } +} + /*********************************************************************** * Update all derived state: @@ -132,6 +151,12 @@ void st_validate_state( struct st_context *st ) struct st_state_flags *state = &st->dirty; GLuint i; + /* Get Mesa driver state. */ + st->dirty.st |= st->ctx->NewDriverState; + st->ctx->NewDriverState = 0; + + check_attrib_edgeflag(st); + /* The bitmap cache is immune to pixel unpack changes. * Note that GLUT makes several calls to glPixelStore for each * bitmap char it draws so this is an important check. diff --git a/mesalib/src/mesa/state_tracker/st_atom.h b/mesalib/src/mesa/state_tracker/st_atom.h index 930a08444..703bc2ab3 100644 --- a/mesalib/src/mesa/state_tracker/st_atom.h +++ b/mesalib/src/mesa/state_tracker/st_atom.h @@ -46,6 +46,7 @@ void st_destroy_atoms( struct st_context *st ); void st_validate_state( struct st_context *st ); +extern const struct st_tracked_state st_update_array; extern const struct st_tracked_state st_update_framebuffer; extern const struct st_tracked_state st_update_clip; extern const struct st_tracked_state st_update_depth_stencil_alpha; @@ -70,4 +71,8 @@ extern const struct st_tracked_state st_update_pixel_transfer; GLuint st_compare_func_to_pipe(GLenum func); +enum pipe_format +st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, + GLboolean normalized, GLboolean integer); + #endif diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c new file mode 100644 index 000000000..d60b0d7a9 --- /dev/null +++ b/mesalib/src/mesa/state_tracker/st_atom_array.c @@ -0,0 +1,588 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2012 Marek Olšák <maraeo@gmail.com> + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/* + * This converts the VBO's vertex attribute/array information into + * Gallium vertex state and binds it. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Marek Olšák <maraeo@gmail.com> + */ + +#include "st_context.h" +#include "st_atom.h" +#include "st_cb_bufferobjects.h" +#include "st_draw.h" +#include "st_program.h" + +#include "cso_cache/cso_context.h" +#include "util/u_math.h" + +#include "main/bufferobj.h" +#include "main/image.h" + + +static GLuint double_types[4] = { + PIPE_FORMAT_R64_FLOAT, + PIPE_FORMAT_R64G64_FLOAT, + PIPE_FORMAT_R64G64B64_FLOAT, + PIPE_FORMAT_R64G64B64A64_FLOAT +}; + +static GLuint float_types[4] = { + PIPE_FORMAT_R32_FLOAT, + PIPE_FORMAT_R32G32_FLOAT, + PIPE_FORMAT_R32G32B32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT +}; + +static GLuint half_float_types[4] = { + PIPE_FORMAT_R16_FLOAT, + PIPE_FORMAT_R16G16_FLOAT, + PIPE_FORMAT_R16G16B16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT +}; + +static GLuint uint_types_norm[4] = { + PIPE_FORMAT_R32_UNORM, + PIPE_FORMAT_R32G32_UNORM, + PIPE_FORMAT_R32G32B32_UNORM, + PIPE_FORMAT_R32G32B32A32_UNORM +}; + +static GLuint uint_types_scale[4] = { + PIPE_FORMAT_R32_USCALED, + PIPE_FORMAT_R32G32_USCALED, + PIPE_FORMAT_R32G32B32_USCALED, + PIPE_FORMAT_R32G32B32A32_USCALED +}; + +static GLuint uint_types_int[4] = { + PIPE_FORMAT_R32_UINT, + PIPE_FORMAT_R32G32_UINT, + PIPE_FORMAT_R32G32B32_UINT, + PIPE_FORMAT_R32G32B32A32_UINT +}; + +static GLuint int_types_norm[4] = { + PIPE_FORMAT_R32_SNORM, + PIPE_FORMAT_R32G32_SNORM, + PIPE_FORMAT_R32G32B32_SNORM, + PIPE_FORMAT_R32G32B32A32_SNORM +}; + +static GLuint int_types_scale[4] = { + PIPE_FORMAT_R32_SSCALED, + PIPE_FORMAT_R32G32_SSCALED, + PIPE_FORMAT_R32G32B32_SSCALED, + PIPE_FORMAT_R32G32B32A32_SSCALED +}; + +static GLuint int_types_int[4] = { + PIPE_FORMAT_R32_SINT, + PIPE_FORMAT_R32G32_SINT, + PIPE_FORMAT_R32G32B32_SINT, + PIPE_FORMAT_R32G32B32A32_SINT +}; + +static GLuint ushort_types_norm[4] = { + PIPE_FORMAT_R16_UNORM, + PIPE_FORMAT_R16G16_UNORM, + PIPE_FORMAT_R16G16B16_UNORM, + PIPE_FORMAT_R16G16B16A16_UNORM +}; + +static GLuint ushort_types_scale[4] = { + PIPE_FORMAT_R16_USCALED, + PIPE_FORMAT_R16G16_USCALED, + PIPE_FORMAT_R16G16B16_USCALED, + PIPE_FORMAT_R16G16B16A16_USCALED +}; + +static GLuint ushort_types_int[4] = { + PIPE_FORMAT_R16_UINT, + PIPE_FORMAT_R16G16_UINT, + PIPE_FORMAT_R16G16B16_UINT, + PIPE_FORMAT_R16G16B16A16_UINT +}; + +static GLuint short_types_norm[4] = { + PIPE_FORMAT_R16_SNORM, + PIPE_FORMAT_R16G16_SNORM, + PIPE_FORMAT_R16G16B16_SNORM, + PIPE_FORMAT_R16G16B16A16_SNORM +}; + +static GLuint short_types_scale[4] = { + PIPE_FORMAT_R16_SSCALED, + PIPE_FORMAT_R16G16_SSCALED, + PIPE_FORMAT_R16G16B16_SSCALED, + PIPE_FORMAT_R16G16B16A16_SSCALED +}; + +static GLuint short_types_int[4] = { + PIPE_FORMAT_R16_SINT, + PIPE_FORMAT_R16G16_SINT, + PIPE_FORMAT_R16G16B16_SINT, + PIPE_FORMAT_R16G16B16A16_SINT +}; + +static GLuint ubyte_types_norm[4] = { + PIPE_FORMAT_R8_UNORM, + PIPE_FORMAT_R8G8_UNORM, + PIPE_FORMAT_R8G8B8_UNORM, + PIPE_FORMAT_R8G8B8A8_UNORM +}; + +static GLuint ubyte_types_scale[4] = { + PIPE_FORMAT_R8_USCALED, + PIPE_FORMAT_R8G8_USCALED, + PIPE_FORMAT_R8G8B8_USCALED, + PIPE_FORMAT_R8G8B8A8_USCALED +}; + +static GLuint ubyte_types_int[4] = { + PIPE_FORMAT_R8_UINT, + PIPE_FORMAT_R8G8_UINT, + PIPE_FORMAT_R8G8B8_UINT, + PIPE_FORMAT_R8G8B8A8_UINT +}; + +static GLuint byte_types_norm[4] = { + PIPE_FORMAT_R8_SNORM, + PIPE_FORMAT_R8G8_SNORM, + PIPE_FORMAT_R8G8B8_SNORM, + PIPE_FORMAT_R8G8B8A8_SNORM +}; + +static GLuint byte_types_scale[4] = { + PIPE_FORMAT_R8_SSCALED, + PIPE_FORMAT_R8G8_SSCALED, + PIPE_FORMAT_R8G8B8_SSCALED, + PIPE_FORMAT_R8G8B8A8_SSCALED +}; + +static GLuint byte_types_int[4] = { + PIPE_FORMAT_R8_SINT, + PIPE_FORMAT_R8G8_SINT, + PIPE_FORMAT_R8G8B8_SINT, + PIPE_FORMAT_R8G8B8A8_SINT +}; + +static GLuint fixed_types[4] = { + PIPE_FORMAT_R32_FIXED, + PIPE_FORMAT_R32G32_FIXED, + PIPE_FORMAT_R32G32B32_FIXED, + PIPE_FORMAT_R32G32B32A32_FIXED +}; + + +/** + * Return a PIPE_FORMAT_x for the given GL datatype and size. + */ +enum pipe_format +st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, + GLboolean normalized, GLboolean integer) +{ + assert((type >= GL_BYTE && type <= GL_DOUBLE) || + type == GL_FIXED || type == GL_HALF_FLOAT || + type == GL_INT_2_10_10_10_REV || + type == GL_UNSIGNED_INT_2_10_10_10_REV); + assert(size >= 1); + assert(size <= 4); + assert(format == GL_RGBA || format == GL_BGRA); + + if (type == GL_INT_2_10_10_10_REV || + type == GL_UNSIGNED_INT_2_10_10_10_REV) { + assert(size == 4); + assert(!integer); + + if (format == GL_BGRA) { + if (type == GL_INT_2_10_10_10_REV) { + if (normalized) + return PIPE_FORMAT_B10G10R10A2_SNORM; + else + return PIPE_FORMAT_B10G10R10A2_SSCALED; + } else { + if (normalized) + return PIPE_FORMAT_B10G10R10A2_UNORM; + else + return PIPE_FORMAT_B10G10R10A2_USCALED; + } + } else { + if (type == GL_INT_2_10_10_10_REV) { + if (normalized) + return PIPE_FORMAT_R10G10B10A2_SNORM; + else + return PIPE_FORMAT_R10G10B10A2_SSCALED; + } else { + if (normalized) + return PIPE_FORMAT_R10G10B10A2_UNORM; + else + return PIPE_FORMAT_R10G10B10A2_USCALED; + } + } + } + + if (format == GL_BGRA) { + /* this is an odd-ball case */ + assert(type == GL_UNSIGNED_BYTE); + assert(normalized); + return PIPE_FORMAT_B8G8R8A8_UNORM; + } + + if (integer) { + switch (type) { + case GL_INT: return int_types_int[size-1]; + case GL_SHORT: return short_types_int[size-1]; + case GL_BYTE: return byte_types_int[size-1]; + case GL_UNSIGNED_INT: return uint_types_int[size-1]; + case GL_UNSIGNED_SHORT: return ushort_types_int[size-1]; + case GL_UNSIGNED_BYTE: return ubyte_types_int[size-1]; + default: assert(0); return 0; + } + } + else if (normalized) { + switch (type) { + case GL_DOUBLE: return double_types[size-1]; + case GL_FLOAT: return float_types[size-1]; + case GL_HALF_FLOAT: return half_float_types[size-1]; + case GL_INT: return int_types_norm[size-1]; + case GL_SHORT: return short_types_norm[size-1]; + case GL_BYTE: return byte_types_norm[size-1]; + case GL_UNSIGNED_INT: return uint_types_norm[size-1]; + case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1]; + case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; + case GL_FIXED: return fixed_types[size-1]; + default: assert(0); return 0; + } + } + else { + switch (type) { + case GL_DOUBLE: return double_types[size-1]; + case GL_FLOAT: return float_types[size-1]; + case GL_HALF_FLOAT: return half_float_types[size-1]; + case GL_INT: return int_types_scale[size-1]; + case GL_SHORT: return short_types_scale[size-1]; + case GL_BYTE: return byte_types_scale[size-1]; + case GL_UNSIGNED_INT: return uint_types_scale[size-1]; + case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1]; + case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; + case GL_FIXED: return fixed_types[size-1]; + default: assert(0); return 0; + } + } + return PIPE_FORMAT_NONE; /* silence compiler warning */ +} + +/** + * Examine the active arrays to determine if we have interleaved + * vertex arrays all living in one VBO, or all living in user space. + */ +static GLboolean +is_interleaved_arrays(const struct st_vertex_program *vp, + const struct st_vp_variant *vpv, + const struct gl_client_array **arrays) +{ + GLuint attr; + const struct gl_buffer_object *firstBufObj = NULL; + GLint firstStride = -1; + const GLubyte *firstPtr = NULL; + GLboolean userSpaceBuffer = GL_FALSE; + + for (attr = 0; attr < vpv->num_inputs; attr++) { + const GLuint mesaAttr = vp->index_to_input[attr]; + const struct gl_client_array *array = arrays[mesaAttr]; + const struct gl_buffer_object *bufObj = array->BufferObj; + const GLsizei stride = array->StrideB; /* in bytes */ + + if (attr == 0) { + /* save info about the first array */ + firstStride = stride; + firstPtr = array->Ptr; + firstBufObj = bufObj; + userSpaceBuffer = !bufObj || !bufObj->Name; + } + else { + /* check if other arrays interleave with the first, in same buffer */ + if (stride != firstStride) + return GL_FALSE; /* strides don't match */ + + if (bufObj != firstBufObj) + return GL_FALSE; /* arrays in different VBOs */ + + if (abs(array->Ptr - firstPtr) > firstStride) + return GL_FALSE; /* arrays start too far apart */ + + if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer) + return GL_FALSE; /* mix of VBO and user-space arrays */ + } + } + + return GL_TRUE; +} + +/** + * Set up for drawing interleaved arrays that all live in one VBO + * or all live in user space. + * \param vbuffer returns vertex buffer info + * \param velements returns vertex element info + */ +static boolean +setup_interleaved_attribs(const struct st_vertex_program *vp, + const struct st_vp_variant *vpv, + const struct gl_client_array **arrays, + struct pipe_vertex_buffer *vbuffer, + struct pipe_vertex_element velements[]) +{ + GLuint attr; + const GLubyte *low_addr = NULL; + GLboolean usingVBO; /* all arrays in a VBO? */ + struct gl_buffer_object *bufobj; + GLsizei stride; + + /* Find the lowest address of the arrays we're drawing, + * Init bufobj and stride. + */ + if (vpv->num_inputs) { + const GLuint mesaAttr0 = vp->index_to_input[0]; + const struct gl_client_array *array = arrays[mesaAttr0]; + + /* Since we're doing interleaved arrays, we know there'll be at most + * one buffer object and the stride will be the same for all arrays. + * Grab them now. + */ + bufobj = array->BufferObj; + stride = array->StrideB; + + low_addr = arrays[vp->index_to_input[0]]->Ptr; + + for (attr = 1; attr < vpv->num_inputs; attr++) { + const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr; + low_addr = MIN2(low_addr, start); + } + } + else { + /* not sure we'll ever have zero inputs, but play it safe */ + bufobj = NULL; + stride = 0; + low_addr = 0; + } + + /* are the arrays in user space? */ + usingVBO = _mesa_is_bufferobj(bufobj); + + for (attr = 0; attr < vpv->num_inputs; attr++) { + const GLuint mesaAttr = vp->index_to_input[attr]; + const struct gl_client_array *array = arrays[mesaAttr]; + unsigned src_offset = (unsigned) (array->Ptr - low_addr); + GLuint element_size = array->_ElementSize; + + assert(element_size == array->Size * _mesa_sizeof_type(array->Type)); + + velements[attr].src_offset = src_offset; + velements[attr].instance_divisor = array->InstanceDivisor; + velements[attr].vertex_buffer_index = 0; + velements[attr].src_format = st_pipe_vertex_format(array->Type, + array->Size, + array->Format, + array->Normalized, + array->Integer); + assert(velements[attr].src_format); + } + + /* + * Return the vbuffer info and setup user-space attrib info, if needed. + */ + if (vpv->num_inputs == 0) { + /* just defensive coding here */ + vbuffer->buffer = NULL; + vbuffer->user_buffer = NULL; + vbuffer->buffer_offset = 0; + vbuffer->stride = 0; + } + else if (usingVBO) { + /* all interleaved arrays in a VBO */ + struct st_buffer_object *stobj = st_buffer_object(bufobj); + + if (!stobj || !stobj->buffer) { + return FALSE; /* out-of-memory error probably */ + } + + vbuffer->buffer = stobj->buffer; + vbuffer->user_buffer = NULL; + vbuffer->buffer_offset = pointer_to_offset(low_addr); + vbuffer->stride = stride; + } + else { + /* all interleaved arrays in user memory */ + vbuffer->buffer = NULL; + vbuffer->user_buffer = low_addr; + vbuffer->buffer_offset = 0; + vbuffer->stride = stride; + } + return TRUE; +} + +/** + * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each + * vertex attribute. + * \param vbuffer returns vertex buffer info + * \param velements returns vertex element info + */ +static boolean +setup_non_interleaved_attribs(struct st_context *st, + const struct st_vertex_program *vp, + const struct st_vp_variant *vpv, + const struct gl_client_array **arrays, + struct pipe_vertex_buffer vbuffer[], + struct pipe_vertex_element velements[]) +{ + struct gl_context *ctx = st->ctx; + GLuint attr; + + for (attr = 0; attr < vpv->num_inputs; attr++) { + const GLuint mesaAttr = vp->index_to_input[attr]; + const struct gl_client_array *array = arrays[mesaAttr]; + struct gl_buffer_object *bufobj = array->BufferObj; + GLsizei stride = array->StrideB; + + assert(array->_ElementSize == array->Size * _mesa_sizeof_type(array->Type)); + + if (_mesa_is_bufferobj(bufobj)) { + /* Attribute data is in a VBO. + * Recall that for VBOs, the gl_client_array->Ptr field is + * really an offset from the start of the VBO, not a pointer. + */ + struct st_buffer_object *stobj = st_buffer_object(bufobj); + + if (!stobj || !stobj->buffer) { + return FALSE; /* out-of-memory error probably */ + } + + vbuffer[attr].buffer = stobj->buffer; + vbuffer[attr].user_buffer = NULL; + vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr); + } + else { + /* wrap user data */ + void *ptr; + + if (array->Ptr) { + ptr = (void *) array->Ptr; + } + else { + /* no array, use ctx->Current.Attrib[] value */ + ptr = (void *) ctx->Current.Attrib[mesaAttr]; + stride = 0; + } + + assert(ptr); + + vbuffer[attr].buffer = NULL; + vbuffer[attr].user_buffer = ptr; + vbuffer[attr].buffer_offset = 0; + } + + /* common-case setup */ + vbuffer[attr].stride = stride; /* in bytes */ + + velements[attr].src_offset = 0; + velements[attr].instance_divisor = array->InstanceDivisor; + velements[attr].vertex_buffer_index = attr; + velements[attr].src_format = st_pipe_vertex_format(array->Type, + array->Size, + array->Format, + array->Normalized, + array->Integer); + assert(velements[attr].src_format); + } + return TRUE; +} + +static void update_array(struct st_context *st) +{ + struct gl_context *ctx = st->ctx; + const struct gl_client_array **arrays = ctx->Array._DrawArrays; + const struct st_vertex_program *vp; + const struct st_vp_variant *vpv; + struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; + unsigned num_vbuffers, num_velements; + + st->vertex_array_out_of_memory = FALSE; + + /* No drawing has been done yet, so do nothing. */ + if (!arrays) + return; + + /* vertex program validation must be done before this */ + vp = st->vp; + vpv = st->vp_variant; + + memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); + + /* + * Setup the vbuffer[] and velements[] arrays. + */ + if (is_interleaved_arrays(vp, vpv, arrays)) { + if (!setup_interleaved_attribs(vp, vpv, arrays, vbuffer, velements)) { + st->vertex_array_out_of_memory = TRUE; + return; + } + + num_vbuffers = 1; + num_velements = vpv->num_inputs; + if (num_velements == 0) + num_vbuffers = 0; + } + else { + if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer, + velements)) { + st->vertex_array_out_of_memory = TRUE; + return; + } + + num_vbuffers = vpv->num_inputs; + num_velements = vpv->num_inputs; + } + + cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer); + cso_set_vertex_elements(st->cso_context, num_velements, velements); +} + + +const struct st_tracked_state st_update_array = { + "st_update_array", /* name */ + { /* dirty */ + (_NEW_PROGRAM | _NEW_BUFFER_OBJECT), /* mesa */ + ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM, /* st */ + }, + update_array /* update */ +}; diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index 9a3f22465..d3f8d1368 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -217,7 +217,7 @@ st_make_drawpix_z_stencil_program(struct st_context *st, if (!p) return NULL; - p->NumInstructions = write_depth ? 2 : 1; + p->NumInstructions = write_depth ? 3 : 1; p->NumInstructions += write_stencil ? 1 : 0; p->Instructions = _mesa_alloc_instructions(p->NumInstructions); @@ -238,6 +238,13 @@ st_make_drawpix_z_stencil_program(struct st_context *st, p->Instructions[ic].TexSrcUnit = 0; p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; ic++; + /* MOV result.color, fragment.color; */ + p->Instructions[ic].Opcode = OPCODE_MOV; + p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; + p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR; + p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; + p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0; + ic++; } if (write_stencil) { @@ -260,8 +267,10 @@ st_make_drawpix_z_stencil_program(struct st_context *st, p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0; p->OutputsWritten = 0; - if (write_depth) + if (write_depth) { p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH); + p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_COLOR); + } if (write_stencil) p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL); diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 55ae65b3c..734b4d9c1 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -88,6 +88,8 @@ struct st_context */ boolean invalidate_on_gl_viewport; + boolean vertex_array_out_of_memory; + /* Some state is contained in constant objects. * Other state is just parameter values. */ diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index 0a06e9995..db8caa566 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -31,10 +31,6 @@ * this function whether the user called glBegin/End, glDrawArrays, * glDrawElements, glEvalMesh, or glCalList, etc. * - * We basically convert the VBO's vertex attribute/array information into - * Gallium vertex state, bind the vertex buffer objects and call - * pipe->draw_vbo(). - * * Authors: * Keith Whitwell <keith@tungstengraphics.com> */ @@ -68,261 +64,6 @@ #include "../glsl/ir_uniform.h" -static GLuint double_types[4] = { - PIPE_FORMAT_R64_FLOAT, - PIPE_FORMAT_R64G64_FLOAT, - PIPE_FORMAT_R64G64B64_FLOAT, - PIPE_FORMAT_R64G64B64A64_FLOAT -}; - -static GLuint float_types[4] = { - PIPE_FORMAT_R32_FLOAT, - PIPE_FORMAT_R32G32_FLOAT, - PIPE_FORMAT_R32G32B32_FLOAT, - PIPE_FORMAT_R32G32B32A32_FLOAT -}; - -static GLuint half_float_types[4] = { - PIPE_FORMAT_R16_FLOAT, - PIPE_FORMAT_R16G16_FLOAT, - PIPE_FORMAT_R16G16B16_FLOAT, - PIPE_FORMAT_R16G16B16A16_FLOAT -}; - -static GLuint uint_types_norm[4] = { - PIPE_FORMAT_R32_UNORM, - PIPE_FORMAT_R32G32_UNORM, - PIPE_FORMAT_R32G32B32_UNORM, - PIPE_FORMAT_R32G32B32A32_UNORM -}; - -static GLuint uint_types_scale[4] = { - PIPE_FORMAT_R32_USCALED, - PIPE_FORMAT_R32G32_USCALED, - PIPE_FORMAT_R32G32B32_USCALED, - PIPE_FORMAT_R32G32B32A32_USCALED -}; - -static GLuint uint_types_int[4] = { - PIPE_FORMAT_R32_UINT, - PIPE_FORMAT_R32G32_UINT, - PIPE_FORMAT_R32G32B32_UINT, - PIPE_FORMAT_R32G32B32A32_UINT -}; - -static GLuint int_types_norm[4] = { - PIPE_FORMAT_R32_SNORM, - PIPE_FORMAT_R32G32_SNORM, - PIPE_FORMAT_R32G32B32_SNORM, - PIPE_FORMAT_R32G32B32A32_SNORM -}; - -static GLuint int_types_scale[4] = { - PIPE_FORMAT_R32_SSCALED, - PIPE_FORMAT_R32G32_SSCALED, - PIPE_FORMAT_R32G32B32_SSCALED, - PIPE_FORMAT_R32G32B32A32_SSCALED -}; - -static GLuint int_types_int[4] = { - PIPE_FORMAT_R32_SINT, - PIPE_FORMAT_R32G32_SINT, - PIPE_FORMAT_R32G32B32_SINT, - PIPE_FORMAT_R32G32B32A32_SINT -}; - -static GLuint ushort_types_norm[4] = { - PIPE_FORMAT_R16_UNORM, - PIPE_FORMAT_R16G16_UNORM, - PIPE_FORMAT_R16G16B16_UNORM, - PIPE_FORMAT_R16G16B16A16_UNORM -}; - -static GLuint ushort_types_scale[4] = { - PIPE_FORMAT_R16_USCALED, - PIPE_FORMAT_R16G16_USCALED, - PIPE_FORMAT_R16G16B16_USCALED, - PIPE_FORMAT_R16G16B16A16_USCALED -}; - -static GLuint ushort_types_int[4] = { - PIPE_FORMAT_R16_UINT, - PIPE_FORMAT_R16G16_UINT, - PIPE_FORMAT_R16G16B16_UINT, - PIPE_FORMAT_R16G16B16A16_UINT -}; - -static GLuint short_types_norm[4] = { - PIPE_FORMAT_R16_SNORM, - PIPE_FORMAT_R16G16_SNORM, - PIPE_FORMAT_R16G16B16_SNORM, - PIPE_FORMAT_R16G16B16A16_SNORM -}; - -static GLuint short_types_scale[4] = { - PIPE_FORMAT_R16_SSCALED, - PIPE_FORMAT_R16G16_SSCALED, - PIPE_FORMAT_R16G16B16_SSCALED, - PIPE_FORMAT_R16G16B16A16_SSCALED -}; - -static GLuint short_types_int[4] = { - PIPE_FORMAT_R16_SINT, - PIPE_FORMAT_R16G16_SINT, - PIPE_FORMAT_R16G16B16_SINT, - PIPE_FORMAT_R16G16B16A16_SINT -}; - -static GLuint ubyte_types_norm[4] = { - PIPE_FORMAT_R8_UNORM, - PIPE_FORMAT_R8G8_UNORM, - PIPE_FORMAT_R8G8B8_UNORM, - PIPE_FORMAT_R8G8B8A8_UNORM -}; - -static GLuint ubyte_types_scale[4] = { - PIPE_FORMAT_R8_USCALED, - PIPE_FORMAT_R8G8_USCALED, - PIPE_FORMAT_R8G8B8_USCALED, - PIPE_FORMAT_R8G8B8A8_USCALED -}; - -static GLuint ubyte_types_int[4] = { - PIPE_FORMAT_R8_UINT, - PIPE_FORMAT_R8G8_UINT, - PIPE_FORMAT_R8G8B8_UINT, - PIPE_FORMAT_R8G8B8A8_UINT -}; - -static GLuint byte_types_norm[4] = { - PIPE_FORMAT_R8_SNORM, - PIPE_FORMAT_R8G8_SNORM, - PIPE_FORMAT_R8G8B8_SNORM, - PIPE_FORMAT_R8G8B8A8_SNORM -}; - -static GLuint byte_types_scale[4] = { - PIPE_FORMAT_R8_SSCALED, - PIPE_FORMAT_R8G8_SSCALED, - PIPE_FORMAT_R8G8B8_SSCALED, - PIPE_FORMAT_R8G8B8A8_SSCALED -}; - -static GLuint byte_types_int[4] = { - PIPE_FORMAT_R8_SINT, - PIPE_FORMAT_R8G8_SINT, - PIPE_FORMAT_R8G8B8_SINT, - PIPE_FORMAT_R8G8B8A8_SINT -}; - -static GLuint fixed_types[4] = { - PIPE_FORMAT_R32_FIXED, - PIPE_FORMAT_R32G32_FIXED, - PIPE_FORMAT_R32G32B32_FIXED, - PIPE_FORMAT_R32G32B32A32_FIXED -}; - - - -/** - * Return a PIPE_FORMAT_x for the given GL datatype and size. - */ -enum pipe_format -st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, - GLboolean normalized, GLboolean integer) -{ - assert((type >= GL_BYTE && type <= GL_DOUBLE) || - type == GL_FIXED || type == GL_HALF_FLOAT || - type == GL_INT_2_10_10_10_REV || - type == GL_UNSIGNED_INT_2_10_10_10_REV); - assert(size >= 1); - assert(size <= 4); - assert(format == GL_RGBA || format == GL_BGRA); - - if (type == GL_INT_2_10_10_10_REV || - type == GL_UNSIGNED_INT_2_10_10_10_REV) { - assert(size == 4); - assert(!integer); - - if (format == GL_BGRA) { - if (type == GL_INT_2_10_10_10_REV) { - if (normalized) - return PIPE_FORMAT_B10G10R10A2_SNORM; - else - return PIPE_FORMAT_B10G10R10A2_SSCALED; - } else { - if (normalized) - return PIPE_FORMAT_B10G10R10A2_UNORM; - else - return PIPE_FORMAT_B10G10R10A2_USCALED; - } - } else { - if (type == GL_INT_2_10_10_10_REV) { - if (normalized) - return PIPE_FORMAT_R10G10B10A2_SNORM; - else - return PIPE_FORMAT_R10G10B10A2_SSCALED; - } else { - if (normalized) - return PIPE_FORMAT_R10G10B10A2_UNORM; - else - return PIPE_FORMAT_R10G10B10A2_USCALED; - } - } - } - - if (format == GL_BGRA) { - /* this is an odd-ball case */ - assert(type == GL_UNSIGNED_BYTE); - assert(normalized); - return PIPE_FORMAT_B8G8R8A8_UNORM; - } - - if (integer) { - switch (type) { - case GL_INT: return int_types_int[size-1]; - case GL_SHORT: return short_types_int[size-1]; - case GL_BYTE: return byte_types_int[size-1]; - case GL_UNSIGNED_INT: return uint_types_int[size-1]; - case GL_UNSIGNED_SHORT: return ushort_types_int[size-1]; - case GL_UNSIGNED_BYTE: return ubyte_types_int[size-1]; - default: assert(0); return 0; - } - } - else if (normalized) { - switch (type) { - case GL_DOUBLE: return double_types[size-1]; - case GL_FLOAT: return float_types[size-1]; - case GL_HALF_FLOAT: return half_float_types[size-1]; - case GL_INT: return int_types_norm[size-1]; - case GL_SHORT: return short_types_norm[size-1]; - case GL_BYTE: return byte_types_norm[size-1]; - case GL_UNSIGNED_INT: return uint_types_norm[size-1]; - case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1]; - case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1]; - case GL_FIXED: return fixed_types[size-1]; - default: assert(0); return 0; - } - } - else { - switch (type) { - case GL_DOUBLE: return double_types[size-1]; - case GL_FLOAT: return float_types[size-1]; - case GL_HALF_FLOAT: return half_float_types[size-1]; - case GL_INT: return int_types_scale[size-1]; - case GL_SHORT: return short_types_scale[size-1]; - case GL_BYTE: return byte_types_scale[size-1]; - case GL_UNSIGNED_INT: return uint_types_scale[size-1]; - case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1]; - case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1]; - case GL_FIXED: return fixed_types[size-1]; - default: assert(0); return 0; - } - } - return PIPE_FORMAT_NONE; /* silence compiler warning */ -} - - /** * This is very similar to vbo_all_varyings_in_vbos() but we are * only interested in per-vertex data. See bug 38626. @@ -342,240 +83,6 @@ all_varyings_in_vbos(const struct gl_client_array *arrays[]) } -/** - * Examine the active arrays to determine if we have interleaved - * vertex arrays all living in one VBO, or all living in user space. - */ -static GLboolean -is_interleaved_arrays(const struct st_vertex_program *vp, - const struct st_vp_variant *vpv, - const struct gl_client_array **arrays) -{ - GLuint attr; - const struct gl_buffer_object *firstBufObj = NULL; - GLint firstStride = -1; - const GLubyte *firstPtr = NULL; - GLboolean userSpaceBuffer = GL_FALSE; - - for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const struct gl_client_array *array = arrays[mesaAttr]; - const struct gl_buffer_object *bufObj = array->BufferObj; - const GLsizei stride = array->StrideB; /* in bytes */ - - if (attr == 0) { - /* save info about the first array */ - firstStride = stride; - firstPtr = array->Ptr; - firstBufObj = bufObj; - userSpaceBuffer = !bufObj || !bufObj->Name; - } - else { - /* check if other arrays interleave with the first, in same buffer */ - if (stride != firstStride) - return GL_FALSE; /* strides don't match */ - - if (bufObj != firstBufObj) - return GL_FALSE; /* arrays in different VBOs */ - - if (abs(array->Ptr - firstPtr) > firstStride) - return GL_FALSE; /* arrays start too far apart */ - - if ((!_mesa_is_bufferobj(bufObj)) != userSpaceBuffer) - return GL_FALSE; /* mix of VBO and user-space arrays */ - } - } - - return GL_TRUE; -} - - -/** - * Set up for drawing interleaved arrays that all live in one VBO - * or all live in user space. - * \param vbuffer returns vertex buffer info - * \param velements returns vertex element info - * \return GL_TRUE for success, GL_FALSE otherwise (probably out of memory) - */ -static GLboolean -setup_interleaved_attribs(struct gl_context *ctx, - const struct st_vertex_program *vp, - const struct st_vp_variant *vpv, - const struct gl_client_array **arrays, - struct pipe_vertex_buffer *vbuffer, - struct pipe_vertex_element velements[]) -{ - GLuint attr; - const GLubyte *low_addr = NULL; - GLboolean usingVBO; /* all arrays in a VBO? */ - struct gl_buffer_object *bufobj; - GLsizei stride; - - /* Find the lowest address of the arrays we're drawing, - * Init bufobj and stride. - */ - if (vpv->num_inputs) { - const GLuint mesaAttr0 = vp->index_to_input[0]; - const struct gl_client_array *array = arrays[mesaAttr0]; - - /* Since we're doing interleaved arrays, we know there'll be at most - * one buffer object and the stride will be the same for all arrays. - * Grab them now. - */ - bufobj = array->BufferObj; - stride = array->StrideB; - - low_addr = arrays[vp->index_to_input[0]]->Ptr; - - for (attr = 1; attr < vpv->num_inputs; attr++) { - const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr; - low_addr = MIN2(low_addr, start); - } - } - else { - /* not sure we'll ever have zero inputs, but play it safe */ - bufobj = NULL; - stride = 0; - low_addr = 0; - } - - /* are the arrays in user space? */ - usingVBO = _mesa_is_bufferobj(bufobj); - - for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const struct gl_client_array *array = arrays[mesaAttr]; - unsigned src_offset = (unsigned) (array->Ptr - low_addr); - GLuint element_size = array->_ElementSize; - - assert(element_size == array->Size * _mesa_sizeof_type(array->Type)); - - velements[attr].src_offset = src_offset; - velements[attr].instance_divisor = array->InstanceDivisor; - velements[attr].vertex_buffer_index = 0; - velements[attr].src_format = st_pipe_vertex_format(array->Type, - array->Size, - array->Format, - array->Normalized, - array->Integer); - assert(velements[attr].src_format); - } - - /* - * Return the vbuffer info and setup user-space attrib info, if needed. - */ - if (vpv->num_inputs == 0) { - /* just defensive coding here */ - vbuffer->buffer = NULL; - vbuffer->user_buffer = NULL; - vbuffer->buffer_offset = 0; - vbuffer->stride = 0; - } - else if (usingVBO) { - /* all interleaved arrays in a VBO */ - struct st_buffer_object *stobj = st_buffer_object(bufobj); - - if (!stobj || !stobj->buffer) { - /* probably out of memory (or zero-sized buffer) */ - return GL_FALSE; - } - - vbuffer->buffer = stobj->buffer; - vbuffer->user_buffer = NULL; - vbuffer->buffer_offset = pointer_to_offset(low_addr); - vbuffer->stride = stride; - } - else { - /* all interleaved arrays in user memory */ - vbuffer->buffer = NULL; - vbuffer->user_buffer = low_addr; - vbuffer->buffer_offset = 0; - vbuffer->stride = stride; - } - - return GL_TRUE; -} - - -/** - * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each - * vertex attribute. - * \param vbuffer returns vertex buffer info - * \param velements returns vertex element info - * \return GL_TRUE for success, GL_FALSE otherwise (probably out of memory) - */ -static GLboolean -setup_non_interleaved_attribs(struct gl_context *ctx, - const struct st_vertex_program *vp, - const struct st_vp_variant *vpv, - const struct gl_client_array **arrays, - struct pipe_vertex_buffer vbuffer[], - struct pipe_vertex_element velements[]) -{ - GLuint attr; - - for (attr = 0; attr < vpv->num_inputs; attr++) { - const GLuint mesaAttr = vp->index_to_input[attr]; - const struct gl_client_array *array = arrays[mesaAttr]; - struct gl_buffer_object *bufobj = array->BufferObj; - GLsizei stride = array->StrideB; - - assert(array->_ElementSize == array->Size * _mesa_sizeof_type(array->Type)); - - if (_mesa_is_bufferobj(bufobj)) { - /* Attribute data is in a VBO. - * Recall that for VBOs, the gl_client_array->Ptr field is - * really an offset from the start of the VBO, not a pointer. - */ - struct st_buffer_object *stobj = st_buffer_object(bufobj); - - if (!stobj || !stobj->buffer) { - /* probably out of memory (or zero-sized buffer) */ - return GL_FALSE; - } - - vbuffer[attr].buffer = stobj->buffer; - vbuffer[attr].user_buffer = NULL; - vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr); - } - else { - /* wrap user data */ - void *ptr; - - if (array->Ptr) { - ptr = (void *) array->Ptr; - } - else { - /* no array, use ctx->Current.Attrib[] value */ - ptr = (void *) ctx->Current.Attrib[mesaAttr]; - stride = 0; - } - - assert(ptr); - - vbuffer[attr].buffer = NULL; - vbuffer[attr].user_buffer = ptr; - vbuffer[attr].buffer_offset = 0; - } - - /* common-case setup */ - vbuffer[attr].stride = stride; /* in bytes */ - - velements[attr].src_offset = 0; - velements[attr].instance_divisor = array->InstanceDivisor; - velements[attr].vertex_buffer_index = attr; - velements[attr].src_format = st_pipe_vertex_format(array->Type, - array->Size, - array->Format, - array->Normalized, - array->Integer); - assert(velements[attr].src_format); - } - - return GL_TRUE; -} - - static void setup_index_buffer(struct st_context *st, const struct _mesa_index_buffer *ib, @@ -665,58 +172,6 @@ translate_prim(const struct gl_context *ctx, unsigned prim) /** - * Setup vertex arrays and buffers prior to drawing. - * \return GL_TRUE for success, GL_FALSE otherwise (probably out of memory) - */ -static GLboolean -st_validate_varrays(struct gl_context *ctx, - const struct gl_client_array **arrays) -{ - struct st_context *st = st_context(ctx); - const struct st_vertex_program *vp; - const struct st_vp_variant *vpv; - struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; - struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; - unsigned num_vbuffers, num_velements; - - /* must get these after state validation! */ - vp = st->vp; - vpv = st->vp_variant; - - memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs); - - /* - * Setup the vbuffer[] and velements[] arrays. - */ - if (is_interleaved_arrays(vp, vpv, arrays)) { - if (!setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, - velements)) { - return GL_FALSE; - } - - num_vbuffers = 1; - num_velements = vpv->num_inputs; - if (num_velements == 0) - num_vbuffers = 0; - } - else { - if (!setup_non_interleaved_attribs(ctx, vp, vpv, arrays, - vbuffer, velements)) { - return GL_FALSE; - } - - num_vbuffers = vpv->num_inputs; - num_velements = vpv->num_inputs; - } - - cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer); - cso_set_vertex_elements(st->cso_context, num_velements, velements); - - return GL_TRUE; -} - - -/** * This function gets plugged into the VBO module and is called when * we have something to render. * Basically, translate the information into the format expected by gallium. @@ -736,38 +191,16 @@ st_draw_vbo(struct gl_context *ctx, struct pipe_draw_info info; const struct gl_client_array **arrays = ctx->Array._DrawArrays; unsigned i; - GLboolean new_array; /* Mesa core state should have been validated already */ assert(ctx->NewState == 0x0); - /* Get Mesa driver state. */ - st->dirty.st |= ctx->NewDriverState; - ctx->NewDriverState = 0; - - new_array = - (st->dirty.st & (ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM)) || - (st->dirty.mesa & (_NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0; - /* Validate state. */ - if (st->dirty.st) { - GLboolean vertDataEdgeFlags; - - vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj && - arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name; - if (vertDataEdgeFlags != st->vertdata_edgeflags) { - st->vertdata_edgeflags = vertDataEdgeFlags; - st->dirty.st |= ST_NEW_EDGEFLAGS_DATA; - } - + if (st->dirty.st || ctx->NewDriverState) { st_validate_state(st); - if (new_array) { - if (!st_validate_varrays(ctx, arrays)) { - /* probably out of memory, no-op the draw call */ - return; - } - } + if (st->vertex_array_out_of_memory) + return; #if 0 if (MESA_VERBOSE & VERBOSE_GLSL) { diff --git a/mesalib/src/mesa/state_tracker/st_draw.h b/mesalib/src/mesa/state_tracker/st_draw.h index c608051eb..3313fc8c7 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.h +++ b/mesalib/src/mesa/state_tracker/st_draw.h @@ -67,13 +67,6 @@ st_feedback_draw_vbo(struct gl_context *ctx, GLuint max_index, struct gl_transform_feedback_object *tfb_vertcount); -/* Internal function: - */ -extern enum pipe_format -st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, - GLboolean normalized, GLboolean integer); - - /** * When drawing with VBOs, the addresses specified with * glVertex/Color/TexCoordPointer() are really offsets into the VBO, not real |