From 321c01267ae1c446f1bd22b642567fcafa016c02 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 4 Mar 2014 08:57:07 +0100 Subject: libX11 libxcb mesa xserver xcb-proto xkeyboard-config git update 4 Mar 2014 xserver commit b634e909895f6001e7d9543e1350b20c82c8c01c libxcb commit 4ffa6f83b92763eb901c7ddb7c20775e24d507ca libxcb/xcb-proto commit 4270141a7cb3c68f50251be19a5a628aa18553e6 xkeyboard-config commit d9e3d0ec1a48a5f61ea6dd6d20b8682eeecf3a39 libX11 commit d6bd988bc00494914b38b95ee5df77ac4f32f19f libXdmcp commit 089081dca4ba3598c6f9bf401c029378943b5854 libXext commit d5447c0156f556114dbf97d6064c0c7b0fcd5f70 libfontenc commit 0037a42107b952c9d903719615747e760e4e7247 libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909 libXau commit 1e4635be11154dd8262f37b379511bd627defa2a xkbcomp commit 31b90ee4ffc774e0da540277907fc5540c0b012c pixman commit 82d094654a46bd97d47f1f132a01ae0a74b986f3 xextproto commit 66afec3f49e8eb0d4c2e9af7088fc3116d4bafd7 randrproto commit a4a6694c059d74247c16527eef4a0ec9f56bbef6 glproto commit f84853d97d5749308992412a215fa518b6536eb3 mkfontscale commit eac564e0fc9052a39981ea47b271f7f3d2821944 xwininfo commit ba0d1b0da21d2dbdd81098ed5778f3792b472e13 libXft commit 4acfdaf95adb0a05c2a25550bdde036c865902f4 libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63 libxtrans commit 3f0de269abe59353acbd7a5587d68ce0da91db67 fontconfig commit e310d2fac2d874d5aa76c609df70cc7b871c0b6d mesa commit 1a568e0f2b65e4e1e1d19a6dece3a792a33da825 --- mesalib/src/mesa/Makefile.sources | 2 + mesalib/src/mesa/SConscript | 2 + mesalib/src/mesa/drivers/common/meta.c | 1964 ++++++-------------- mesalib/src/mesa/drivers/common/meta.h | 361 ++++ mesalib/src/mesa/drivers/common/meta_blit.c | 825 ++++++++ mesalib/src/mesa/drivers/dri/common/dri_util.c | 26 +- mesalib/src/mesa/main/api_arrayelt.c | 14 +- mesalib/src/mesa/main/api_loopback.c | 1 - mesalib/src/mesa/main/api_loopback.h | 1 - mesalib/src/mesa/main/api_validate.c | 7 +- mesalib/src/mesa/main/arrayobj.c | 12 +- mesalib/src/mesa/main/attrib.c | 1 + mesalib/src/mesa/main/bufferobj.c | 443 +++-- mesalib/src/mesa/main/bufferobj.h | 23 +- mesalib/src/mesa/main/context.c | 114 +- mesalib/src/mesa/main/dd.h | 21 +- mesalib/src/mesa/main/dlist.c | 9 +- mesalib/src/mesa/main/drawpix.c | 4 +- mesalib/src/mesa/main/enable.c | 33 +- mesalib/src/mesa/main/errors.c | 487 +++-- mesalib/src/mesa/main/errors.h | 3 + mesalib/src/mesa/main/execmem.c | 11 +- mesalib/src/mesa/main/extensions.c | 5 +- mesalib/src/mesa/main/fbobject.c | 22 +- mesalib/src/mesa/main/format_pack.c | 22 +- mesalib/src/mesa/main/format_unpack.c | 34 +- mesalib/src/mesa/main/formats.c | 16 +- mesalib/src/mesa/main/formats.h | 100 +- mesalib/src/mesa/main/framebuffer.c | 14 +- mesalib/src/mesa/main/get.c | 21 + mesalib/src/mesa/main/get_hash_params.py | 6 +- mesalib/src/mesa/main/getstring.c | 20 +- mesalib/src/mesa/main/glformats.c | 24 +- mesalib/src/mesa/main/hash.c | 45 +- mesalib/src/mesa/main/imports.h | 2 +- mesalib/src/mesa/main/mtypes.h | 94 +- mesalib/src/mesa/main/pbo.c | 22 +- mesalib/src/mesa/main/pipelineobj.c | 445 +++++ mesalib/src/mesa/main/pipelineobj.h | 95 + mesalib/src/mesa/main/readpix.c | 4 +- mesalib/src/mesa/main/renderbuffer.c | 12 +- mesalib/src/mesa/main/samplerobj.c | 12 +- mesalib/src/mesa/main/shaderapi.c | 131 +- mesalib/src/mesa/main/shaderapi.h | 8 + mesalib/src/mesa/main/shaderobj.c | 1 + mesalib/src/mesa/main/shared.c | 22 +- mesalib/src/mesa/main/syncobj.c | 14 +- mesalib/src/mesa/main/texcompress_etc.c | 3 +- mesalib/src/mesa/main/texformat.c | 6 +- mesalib/src/mesa/main/texgetimage.c | 25 +- mesalib/src/mesa/main/teximage.c | 44 +- mesalib/src/mesa/main/teximage.h | 4 +- mesalib/src/mesa/main/texobj.c | 34 +- mesalib/src/mesa/main/texparam.c | 3 + mesalib/src/mesa/main/texstore.c | 8 +- mesalib/src/mesa/main/uniform_query.cpp | 36 + mesalib/src/mesa/main/uniforms.c | 393 ++++ mesalib/src/mesa/main/uniforms.h | 83 + mesalib/src/mesa/main/vdpau.c | 9 +- mesalib/src/mesa/main/vdpau.h | 2 +- mesalib/src/mesa/main/version.c | 1 - mesalib/src/mesa/program/ir_to_mesa.cpp | 25 +- mesalib/src/mesa/program/program.c | 9 +- mesalib/src/mesa/state_tracker/st_atom_scissor.c | 77 +- mesalib/src/mesa/state_tracker/st_atom_viewport.c | 37 +- .../src/mesa/state_tracker/st_cb_bufferobjects.c | 133 +- .../src/mesa/state_tracker/st_cb_bufferobjects.h | 2 +- .../src/mesa/state_tracker/st_cb_texturebarrier.c | 17 + mesalib/src/mesa/state_tracker/st_context.h | 4 +- mesalib/src/mesa/state_tracker/st_draw_feedback.c | 2 +- mesalib/src/mesa/state_tracker/st_extensions.c | 22 +- mesalib/src/mesa/state_tracker/st_format.c | 8 +- mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 121 +- mesalib/src/mesa/state_tracker/st_manager.c | 9 +- mesalib/src/mesa/state_tracker/st_program.c | 10 + mesalib/src/mesa/swrast/s_depth.c | 14 +- mesalib/src/mesa/swrast/s_drawpix.c | 4 +- mesalib/src/mesa/swrast/s_renderbuffer.c | 2 +- mesalib/src/mesa/swrast/s_stencil.c | 2 +- mesalib/src/mesa/swrast/s_texfetch.c | 4 +- mesalib/src/mesa/swrast/s_texfetch_tmp.h | 4 +- mesalib/src/mesa/tnl/t_draw.c | 21 +- mesalib/src/mesa/vbo/vbo_exec_api.c | 10 +- mesalib/src/mesa/vbo/vbo_exec_array.c | 40 +- mesalib/src/mesa/vbo/vbo_exec_draw.c | 30 +- mesalib/src/mesa/vbo/vbo_primitive_restart.c | 17 +- mesalib/src/mesa/vbo/vbo_rebase.c | 9 +- mesalib/src/mesa/vbo/vbo_save_api.c | 17 +- mesalib/src/mesa/vbo/vbo_save_draw.c | 6 +- mesalib/src/mesa/vbo/vbo_split_copy.c | 28 +- 90 files changed, 4451 insertions(+), 2439 deletions(-) create mode 100644 mesalib/src/mesa/drivers/common/meta_blit.c create mode 100644 mesalib/src/mesa/main/pipelineobj.c create mode 100644 mesalib/src/mesa/main/pipelineobj.h (limited to 'mesalib/src/mesa') diff --git a/mesalib/src/mesa/Makefile.sources b/mesalib/src/mesa/Makefile.sources index bd02d3ee8..f6f4062a4 100644 --- a/mesalib/src/mesa/Makefile.sources +++ b/mesalib/src/mesa/Makefile.sources @@ -69,6 +69,7 @@ MAIN_FILES = \ $(SRCDIR)main/pack.c \ $(SRCDIR)main/pbo.c \ $(SRCDIR)main/performance_monitor.c \ + $(SRCDIR)main/pipelineobj.c \ $(SRCDIR)main/pixel.c \ $(SRCDIR)main/pixelstore.c \ $(SRCDIR)main/pixeltransfer.c \ @@ -319,6 +320,7 @@ SPARC_FILES = \ COMMON_DRIVER_FILES = \ $(SRCDIR)drivers/common/driverfuncs.c \ + $(SRCDIR)drivers/common/meta_blit.c \ $(SRCDIR)drivers/common/meta.c diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index b52bbdc23..7f4e41983 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -98,6 +98,7 @@ main_sources = [ 'main/pack.c', 'main/pbo.c', 'main/performance_monitor.c', + 'main/pipelineobj.c', 'main/pixel.c', 'main/pixelstore.c', 'main/pixeltransfer.c', @@ -325,6 +326,7 @@ program_sources = [ common_driver_sources = [ 'drivers/common/driverfuncs.c', 'drivers/common/meta.c', + 'drivers/common/meta_blit.c' ] mesa_sources = ( diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index f12bcaab1..cde34f99f 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -51,6 +51,8 @@ #include "main/macros.h" #include "main/matrix.h" #include "main/mipmap.h" +#include "main/multisample.h" +#include "main/objectlabel.h" #include "main/pixel.h" #include "main/pbo.h" #include "main/polygon.h" @@ -82,283 +84,18 @@ /** Return offset in bytes of the field within a vertex struct */ #define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) -/** - * State which we may save/restore across meta ops. - * XXX this may be incomplete... - */ -struct save_state -{ - GLbitfield SavedState; /**< bitmask of MESA_META_* flags */ - - /** MESA_META_CLEAR (and others?) */ - struct gl_query_object *CurrentOcclusionObject; - - /** MESA_META_ALPHA_TEST */ - GLboolean AlphaEnabled; - GLenum AlphaFunc; - GLclampf AlphaRef; - - /** MESA_META_BLEND */ - GLbitfield BlendEnabled; - GLboolean ColorLogicOpEnabled; - - /** MESA_META_COLOR_MASK */ - GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; - - /** MESA_META_DEPTH_TEST */ - struct gl_depthbuffer_attrib Depth; - - /** MESA_META_FOG */ - GLboolean Fog; - - /** MESA_META_PIXEL_STORE */ - struct gl_pixelstore_attrib Pack, Unpack; - - /** MESA_META_PIXEL_TRANSFER */ - GLfloat RedBias, RedScale; - GLfloat GreenBias, GreenScale; - GLfloat BlueBias, BlueScale; - GLfloat AlphaBias, AlphaScale; - GLfloat DepthBias, DepthScale; - GLboolean MapColorFlag; - - /** MESA_META_RASTERIZATION */ - GLenum FrontPolygonMode, BackPolygonMode; - GLboolean PolygonOffset; - GLboolean PolygonSmooth; - GLboolean PolygonStipple; - GLboolean PolygonCull; - - /** MESA_META_SCISSOR */ - struct gl_scissor_attrib Scissor; - - /** MESA_META_SHADER */ - GLboolean VertexProgramEnabled; - struct gl_vertex_program *VertexProgram; - GLboolean FragmentProgramEnabled; - struct gl_fragment_program *FragmentProgram; - GLboolean ATIFragmentShaderEnabled; - struct gl_shader_program *Shader[MESA_SHADER_STAGES]; - struct gl_shader_program *ActiveShader; - - /** MESA_META_STENCIL_TEST */ - struct gl_stencil_attrib Stencil; - - /** MESA_META_TRANSFORM */ - GLenum MatrixMode; - GLfloat ModelviewMatrix[16]; - GLfloat ProjectionMatrix[16]; - GLfloat TextureMatrix[16]; - - /** MESA_META_CLIP */ - GLbitfield ClipPlanesEnabled; - - /** MESA_META_TEXTURE */ - GLuint ActiveUnit; - GLuint ClientActiveUnit; - /** for unit[0] only */ - struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS]; - /** mask of TEXTURE_2D_BIT, etc */ - GLbitfield TexEnabled[MAX_TEXTURE_UNITS]; - GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS]; - GLuint EnvMode; /* unit[0] only */ - - /** MESA_META_VERTEX */ - struct gl_vertex_array_object *VAO; - struct gl_buffer_object *ArrayBufferObj; - - /** MESA_META_VIEWPORT */ - GLfloat ViewportX, ViewportY, ViewportW, ViewportH; - GLclampd DepthNear, DepthFar; - - /** MESA_META_CLAMP_FRAGMENT_COLOR */ - GLenum ClampFragmentColor; - - /** MESA_META_CLAMP_VERTEX_COLOR */ - GLenum ClampVertexColor; - - /** MESA_META_CONDITIONAL_RENDER */ - struct gl_query_object *CondRenderQuery; - GLenum CondRenderMode; - - /** MESA_META_SELECT_FEEDBACK */ - GLenum RenderMode; - struct gl_selection Select; - struct gl_feedback Feedback; - - /** MESA_META_MULTISAMPLE */ - GLboolean MultisampleEnabled; - - /** MESA_META_FRAMEBUFFER_SRGB */ - GLboolean sRGBEnabled; - - /** Miscellaneous (always disabled) */ - GLboolean Lighting; - GLboolean RasterDiscard; - GLboolean TransformFeedbackNeedsResume; -}; - -/** - * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc. - * This is currently shared by all the meta ops. But we could create a - * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc. - */ -struct temp_texture -{ - GLuint TexObj; - GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */ - GLsizei MinSize; /**< Min texture size to allocate */ - GLsizei MaxSize; /**< Max possible texture size */ - GLboolean NPOT; /**< Non-power of two size OK? */ - GLsizei Width, Height; /**< Current texture size */ - GLenum IntFormat; - GLfloat Sright, Ttop; /**< right, top texcoords */ -}; - - -/** - * State for glBlitFramebufer() - */ -struct blit_state -{ - GLuint VAO; - GLuint VBO; - GLuint DepthFP; - GLuint ShaderProg; - GLuint RectShaderProg; - struct temp_texture depthTex; -}; - +static struct blit_shader * +choose_blit_shader(GLenum target, struct blit_shader_table *table); -/** - * State for glClear() - */ -struct clear_state -{ - GLuint VAO; - GLuint VBO; - GLuint ShaderProg; - GLint ColorLocation; - GLint LayerLocation; - - GLuint IntegerShaderProg; - GLint IntegerColorLocation; - GLint IntegerLayerLocation; -}; - - -/** - * State for glCopyPixels() - */ -struct copypix_state -{ - GLuint VAO; - GLuint VBO; -}; - - -/** - * State for glDrawPixels() - */ -struct drawpix_state -{ - GLuint VAO; - - GLuint StencilFP; /**< Fragment program for drawing stencil images */ - GLuint DepthFP; /**< Fragment program for drawing depth images */ -}; - - -/** - * State for glBitmap() - */ -struct bitmap_state -{ - GLuint VAO; - GLuint VBO; - struct temp_texture Tex; /**< separate texture from other meta ops */ -}; - -/** - * State for GLSL texture sampler which is used to generate fragment - * shader in _mesa_meta_generate_mipmap(). - */ -struct glsl_sampler { - const char *type; - const char *func; - const char *texcoords; - GLuint shader_prog; -}; - -/** - * State for _mesa_meta_generate_mipmap() - */ -struct gen_mipmap_state -{ - GLuint VAO; - GLuint VBO; - GLuint FBO; - GLuint Sampler; - GLuint ShaderProg; - struct glsl_sampler sampler_1d; - struct glsl_sampler sampler_2d; - struct glsl_sampler sampler_3d; - struct glsl_sampler sampler_cubemap; - struct glsl_sampler sampler_1d_array; - struct glsl_sampler sampler_2d_array; -}; - -/** - * State for texture decompression - */ -struct decompress_state -{ - GLuint VAO; - GLuint VBO, FBO, RBO, Sampler; - GLint Width, Height; -}; - -/** - * State for glDrawTex() - */ -struct drawtex_state -{ - GLuint VAO; - GLuint VBO; -}; - -#define MAX_META_OPS_DEPTH 8 -/** - * All per-context meta state. - */ -struct gl_meta_state -{ - /** Stack of state saved during meta-ops */ - struct save_state Save[MAX_META_OPS_DEPTH]; - /** Save stack depth */ - GLuint SaveStackDepth; - - struct temp_texture TempTex; - - struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */ - struct clear_state Clear; /**< For _mesa_meta_Clear() */ - struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */ - struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */ - struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */ - struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */ - struct decompress_state Decompress; /**< For texture decompression */ - struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */ -}; - -static void meta_glsl_blit_cleanup(struct blit_state *blit); static void cleanup_temp_texture(struct temp_texture *tex); static void meta_glsl_clear_cleanup(struct clear_state *clear); static void meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap); static void meta_decompress_cleanup(struct decompress_state *decompress); static void meta_drawpix_cleanup(struct drawpix_state *drawpix); -static GLuint -compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB *source) +GLuint +_mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target, + const GLcharARB *source) { GLuint shader; GLint ok, size; @@ -384,7 +121,7 @@ compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB return 0; } - _mesa_GetProgramInfoLog(shader, size, NULL, info); + _mesa_GetShaderInfoLog(shader, size, NULL, info); _mesa_problem(ctx, "meta program compile failed:\n%s\n" "source:\n%s\n", @@ -396,8 +133,8 @@ compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB return 0; } -static GLuint -link_program_with_debug(struct gl_context *ctx, GLuint program) +GLuint +_mesa_meta_link_program_with_debug(struct gl_context *ctx, GLuint program) { GLint ok, size; GLchar *info; @@ -424,6 +161,182 @@ link_program_with_debug(struct gl_context *ctx, GLuint program) return 0; } +/** + * Generate a generic shader to blit from a texture to a framebuffer + * + * \param ctx Current GL context + * \param texTarget Texture target that will be the source of the blit + * + * \returns a handle to a shader program on success or zero on failure. + */ +void +_mesa_meta_setup_blit_shader(struct gl_context *ctx, + GLenum target, + struct blit_shader_table *table) +{ + const char *vs_source; + char *fs_source; + GLuint vs, fs; + void *const mem_ctx = ralloc_context(NULL); + struct blit_shader *shader = choose_blit_shader(target, table); + char *name; + + assert(shader != NULL); + + if (shader->shader_prog != 0) { + _mesa_UseProgram(shader->shader_prog); + return; + } + + if (ctx->Const.GLSLVersion < 130) { + vs_source = + "attribute vec2 position;\n" + "attribute vec4 textureCoords;\n" + "varying vec4 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"; + + fs_source = ralloc_asprintf(mem_ctx, + "#extension GL_EXT_texture_array : enable\n" + "#extension GL_ARB_texture_cube_map_array: enable\n" + "uniform %s texSampler;\n" + "varying vec4 texCoords;\n" + "void main()\n" + "{\n" + " gl_FragColor = %s(texSampler, %s);\n" + " gl_FragDepth = gl_FragColor.x;\n" + "}\n", + shader->type, + shader->func, shader->texcoords); + } + else { + vs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "in vec2 position;\n" + "in vec4 textureCoords;\n" + "out vec4 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"); + fs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "#extension GL_ARB_texture_cube_map_array: enable\n" + "uniform %s texSampler;\n" + "in vec4 texCoords;\n" + "out vec4 out_color;\n" + "\n" + "void main()\n" + "{\n" + " out_color = texture(texSampler, %s);\n" + " gl_FragDepth = out_color.x;\n" + "}\n", + shader->type, + shader->texcoords); + } + + vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); + fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); + + shader->shader_prog = _mesa_CreateProgramObjectARB(); + _mesa_AttachShader(shader->shader_prog, fs); + _mesa_DeleteObjectARB(fs); + _mesa_AttachShader(shader->shader_prog, vs); + _mesa_DeleteObjectARB(vs); + _mesa_BindAttribLocation(shader->shader_prog, 0, "position"); + _mesa_BindAttribLocation(shader->shader_prog, 1, "texcoords"); + _mesa_meta_link_program_with_debug(ctx, shader->shader_prog); + name = ralloc_asprintf(mem_ctx, "%s blit", shader->type); + _mesa_ObjectLabel(GL_PROGRAM, shader->shader_prog, -1, name); + ralloc_free(mem_ctx); + + _mesa_UseProgram(shader->shader_prog); +} + +/** + * Configure vertex buffer and vertex array objects for tests + * + * Regardless of whether a new VAO and new VBO are created, the objects + * referenced by \c VAO and \c VBO will be bound into the GL state vector + * when this function terminates. + * + * \param VAO Storage for vertex array object handle. If 0, a new VAO + * will be created. + * \param VBO Storage for vertex buffer object handle. If 0, a new VBO + * will be created. The new VBO will have storage for 4 + * \c vertex structures. + * \param use_generic_attributes Should generic attributes 0 and 1 be used, + * or should traditional, fixed-function color and texture + * coordinate be used? + * \param vertex_size Number of components for attribute 0 / vertex. + * \param texcoord_size Number of components for attribute 1 / texture + * coordinate. If this is 0, attribute 1 will not be set or + * enabled. + * \param color_size Number of components for attribute 1 / primary color. + * If this is 0, attribute 1 will not be set or enabled. + * + * \note If \c use_generic_attributes is \c true, \c color_size must be zero. + * Use \c texcoord_size instead. + */ +void +_mesa_meta_setup_vertex_objects(GLuint *VAO, GLuint *VBO, + bool use_generic_attributes, + unsigned vertex_size, unsigned texcoord_size, + unsigned color_size) +{ + if (*VAO == 0) { + assert(*VBO == 0); + + /* create vertex array object */ + _mesa_GenVertexArrays(1, VAO); + _mesa_BindVertexArray(*VAO); + + /* create vertex array buffer */ + _mesa_GenBuffers(1, VBO); + _mesa_BindBuffer(GL_ARRAY_BUFFER, *VBO); + _mesa_BufferData(GL_ARRAY_BUFFER, 4 * sizeof(struct vertex), NULL, + GL_DYNAMIC_DRAW); + + /* setup vertex arrays */ + if (use_generic_attributes) { + assert(color_size == 0); + + _mesa_VertexAttribPointer(0, vertex_size, GL_FLOAT, GL_FALSE, + sizeof(struct vertex), OFFSET(x)); + _mesa_EnableVertexAttribArray(0); + + if (texcoord_size > 0) { + _mesa_VertexAttribPointer(1, texcoord_size, GL_FLOAT, GL_FALSE, + sizeof(struct vertex), OFFSET(tex)); + _mesa_EnableVertexAttribArray(1); + } + } else { + _mesa_VertexPointer(vertex_size, GL_FLOAT, sizeof(struct vertex), + OFFSET(x)); + _mesa_EnableClientState(GL_VERTEX_ARRAY); + + if (texcoord_size > 0) { + _mesa_TexCoordPointer(texcoord_size, GL_FLOAT, + sizeof(struct vertex), OFFSET(tex)); + _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (color_size > 0) { + _mesa_ColorPointer(color_size, GL_FLOAT, + sizeof(struct vertex), OFFSET(r)); + _mesa_EnableClientState(GL_COLOR_ARRAY); + } + } + } else { + _mesa_BindVertexArray(*VAO); + _mesa_BindBuffer(GL_ARRAY_BUFFER, *VBO); + } +} + /** * Initialize meta-ops for a context. * To be called once during context creation. @@ -446,7 +359,7 @@ _mesa_meta_free(struct gl_context *ctx) { GET_CURRENT_CONTEXT(old_context); _mesa_make_current(ctx, NULL, NULL); - meta_glsl_blit_cleanup(&ctx->Meta->Blit); + _mesa_meta_glsl_blit_cleanup(&ctx->Meta->Blit); meta_glsl_clear_cleanup(&ctx->Meta->Clear); meta_glsl_generate_mipmap_cleanup(&ctx->Meta->Mipmap); cleanup_temp_texture(&ctx->Meta->TempTex); @@ -480,6 +393,13 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) memset(save, 0, sizeof(*save)); save->SavedState = state; + /* We always push into desktop GL mode and pop out at the end. No sense in + * writing our shaders varying based on the user's context choice, when + * Mesa can handle either. + */ + save->API = ctx->API; + ctx->API = API_OPENGL_COMPAT; + /* Pausing transform feedback needs to be done early, or else we won't be * able to change other state. */ @@ -539,9 +459,7 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); } - if ((state & MESA_META_FOG) - && ctx->API != API_OPENGL_CORE - && ctx->API != API_OPENGLES2) { + if (state & MESA_META_FOG) { save->Fog = ctx->Fog.Enabled; if (ctx->Fog.Enabled) _mesa_set_enable(ctx, GL_FOG, GL_FALSE); @@ -586,10 +504,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) save->PolygonCull = ctx->Polygon.CullFlag; _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE); - if (ctx->API == API_OPENGL_COMPAT) { - _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); - _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); - } + _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); + _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE); } @@ -601,21 +517,21 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) if (state & MESA_META_SHADER) { int i; - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_vertex_program) { + if (ctx->Extensions.ARB_vertex_program) { save->VertexProgramEnabled = ctx->VertexProgram.Enabled; _mesa_reference_vertprog(ctx, &save->VertexProgram, ctx->VertexProgram.Current); _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_fragment_program) { + if (ctx->Extensions.ARB_fragment_program) { save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled; _mesa_reference_fragprog(ctx, &save->FragmentProgram, ctx->FragmentProgram.Current); _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ATI_fragment_shader) { + if (ctx->Extensions.ATI_fragment_shader) { save->ATIFragmentShaderEnabled = ctx->ATIFragmentShader.Enabled; _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, GL_FALSE); } @@ -645,33 +561,24 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) save->EnvMode = ctx->Texture.Unit[0].EnvMode; /* Disable all texture units */ - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled; - save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled; - if (ctx->Texture.Unit[u].Enabled || - ctx->Texture.Unit[u].TexGenEnabled) { - _mesa_ActiveTexture(GL_TEXTURE0 + u); - _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); - if (ctx->Extensions.ARB_texture_cube_map) - _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); - if (_mesa_is_gles(ctx) && - ctx->Extensions.OES_EGL_image_external) - _mesa_set_enable(ctx, GL_TEXTURE_EXTERNAL_OES, GL_FALSE); - - if (ctx->API == API_OPENGL_COMPAT) { - _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE); - if (ctx->Extensions.NV_texture_rectangle) - _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); - _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); - } else { - _mesa_set_enable(ctx, GL_TEXTURE_GEN_STR_OES, GL_FALSE); - } - } + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled; + save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled; + if (ctx->Texture.Unit[u].Enabled || + ctx->Texture.Unit[u].TexGenEnabled) { + _mesa_ActiveTexture(GL_TEXTURE0 + u); + _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); + if (ctx->Extensions.ARB_texture_cube_map) + _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); + + _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE); + if (ctx->Extensions.NV_texture_rectangle) + _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); } } @@ -684,9 +591,7 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) /* set defaults for unit[0] */ _mesa_ActiveTexture(GL_TEXTURE0); _mesa_ClientActiveTexture(GL_TEXTURE0); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } if (state & MESA_META_TRANSFORM) { @@ -799,9 +704,20 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) } if (state & MESA_META_MULTISAMPLE) { - save->MultisampleEnabled = ctx->Multisample.Enabled; + save->Multisample = ctx->Multisample; /* struct copy */ + if (ctx->Multisample.Enabled) _mesa_set_multisample(ctx, GL_FALSE); + if (ctx->Multisample.SampleCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_COVERAGE, GL_FALSE); + if (ctx->Multisample.SampleAlphaToCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_COVERAGE, GL_FALSE); + if (ctx->Multisample.SampleAlphaToOne) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_ONE, GL_FALSE); + if (ctx->Multisample.SampleShading) + _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_FALSE); + if (ctx->Multisample.SampleMask) + _mesa_set_enable(ctx, GL_SAMPLE_MASK, GL_FALSE); } if (state & MESA_META_FRAMEBUFFER_SRGB) { @@ -892,9 +808,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_DepthMask(save->Depth.Mask); } - if ((state & MESA_META_FOG) - && ctx->API != API_OPENGL_CORE - && ctx->API != API_OPENGLES2) { + if (state & MESA_META_FOG) { _mesa_set_enable(ctx, GL_FOG, save->Fog); } @@ -918,18 +832,10 @@ _mesa_meta_end(struct gl_context *ctx) } if (state & MESA_META_RASTERIZATION) { - /* Core context requires that front and back mode be the same. - */ - if (ctx->API == API_OPENGL_CORE) { - _mesa_PolygonMode(GL_FRONT_AND_BACK, save->FrontPolygonMode); - } else { - _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); - _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); - } - if (ctx->API == API_OPENGL_COMPAT) { - _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); - _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); - } + _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); + _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); + _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); + _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset); _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull); } @@ -949,7 +855,7 @@ _mesa_meta_end(struct gl_context *ctx) } if (state & MESA_META_SHADER) { - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_vertex_program) { + if (ctx->Extensions.ARB_vertex_program) { _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, save->VertexProgramEnabled); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, @@ -957,7 +863,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_fragment_program) { + if (ctx->Extensions.ARB_fragment_program) { _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, save->FragmentProgramEnabled); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, @@ -965,7 +871,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); } - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ATI_fragment_shader) { + if (ctx->Extensions.ATI_fragment_shader) { _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, save->ATIFragmentShaderEnabled); } @@ -996,7 +902,7 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); _mesa_ClearStencil(stencil->Clear); - if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_stencil_two_side) { + if (ctx->Extensions.EXT_stencil_two_side) { _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, stencil->TestTwoSide); _mesa_ActiveStencilFaceEXT(stencil->ActiveFace @@ -1028,9 +934,7 @@ _mesa_meta_end(struct gl_context *ctx) ASSERT(ctx->Texture.CurrentUnit == 0); /* restore texenv for unit[0] */ - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); - } + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); /* restore texture objects for unit[0] only */ for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { @@ -1043,17 +947,15 @@ _mesa_meta_end(struct gl_context *ctx) } /* Restore fixed function texture enables, texgen */ - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { - if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) { - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - ctx->Texture.Unit[u].Enabled = save->TexEnabled[u]; - } + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + ctx->Texture.Unit[u].Enabled = save->TexEnabled[u]; + } - if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) { - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u]; - } + if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u]; } } @@ -1137,8 +1039,30 @@ _mesa_meta_end(struct gl_context *ctx) } if (state & MESA_META_MULTISAMPLE) { - if (ctx->Multisample.Enabled != save->MultisampleEnabled) - _mesa_set_multisample(ctx, save->MultisampleEnabled); + struct gl_multisample_attrib *ctx_ms = &ctx->Multisample; + struct gl_multisample_attrib *save_ms = &save->Multisample; + + if (ctx_ms->Enabled != save_ms->Enabled) + _mesa_set_multisample(ctx, save_ms->Enabled); + if (ctx_ms->SampleCoverage != save_ms->SampleCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_COVERAGE, save_ms->SampleCoverage); + if (ctx_ms->SampleAlphaToCoverage != save_ms->SampleAlphaToCoverage) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_COVERAGE, save_ms->SampleAlphaToCoverage); + if (ctx_ms->SampleAlphaToOne != save_ms->SampleAlphaToOne) + _mesa_set_enable(ctx, GL_SAMPLE_ALPHA_TO_ONE, save_ms->SampleAlphaToOne); + if (ctx_ms->SampleCoverageValue != save_ms->SampleCoverageValue || + ctx_ms->SampleCoverageInvert != save_ms->SampleCoverageInvert) { + _mesa_SampleCoverage(save_ms->SampleCoverageValue, + save_ms->SampleCoverageInvert); + } + if (ctx_ms->SampleShading != save_ms->SampleShading) + _mesa_set_enable(ctx, GL_SAMPLE_SHADING, save_ms->SampleShading); + if (ctx_ms->SampleMask != save_ms->SampleMask) + _mesa_set_enable(ctx, GL_SAMPLE_MASK, save_ms->SampleMask); + if (ctx_ms->SampleMaskValue != save_ms->SampleMaskValue) + _mesa_SampleMaski(0, save_ms->SampleMaskValue); + if (ctx_ms->MinSampleShadingValue != save_ms->MinSampleShadingValue) + _mesa_MinSampleShading(save_ms->MinSampleShadingValue); } if (state & MESA_META_FRAMEBUFFER_SRGB) { @@ -1157,6 +1081,8 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_ResumeTransformFeedback(); ctx->Meta->SaveStackDepth--; + + ctx->API = save->API; } @@ -1224,8 +1150,8 @@ cleanup_temp_texture(struct temp_texture *tex) * Return pointer to temp_texture info for non-bitmap ops. * This does some one-time init if needed. */ -static struct temp_texture * -get_temp_texture(struct gl_context *ctx) +struct temp_texture * +_mesa_meta_get_temp_texture(struct gl_context *ctx) { struct temp_texture *tex = &ctx->Meta->TempTex; @@ -1258,8 +1184,8 @@ get_bitmap_temp_texture(struct gl_context *ctx) * Return pointer to depth temp_texture. * This does some one-time init if needed. */ -static struct temp_texture * -get_temp_depth_texture(struct gl_context *ctx) +struct temp_texture * +_mesa_meta_get_temp_depth_texture(struct gl_context *ctx) { struct temp_texture *tex = &ctx->Meta->Blit.depthTex; @@ -1279,9 +1205,9 @@ get_temp_depth_texture(struct gl_context *ctx) * * \return GL_TRUE if new texture is needed, GL_FALSE otherwise */ -static GLboolean -alloc_texture(struct temp_texture *tex, - GLsizei width, GLsizei height, GLenum intFormat) +GLboolean +_mesa_meta_alloc_texture(struct temp_texture *tex, + GLsizei width, GLsizei height, GLenum intFormat) { GLboolean newTex = GL_FALSE; @@ -1332,19 +1258,22 @@ alloc_texture(struct temp_texture *tex, /** * Setup/load texture for glCopyPixels or glBlitFramebuffer. */ -static void -setup_copypix_texture(struct gl_context *ctx, - struct temp_texture *tex, - GLboolean newTex, - GLint srcX, GLint srcY, - GLsizei width, GLsizei height, GLenum intFormat, - GLenum filter) +void +_mesa_meta_setup_copypix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLint srcX, GLint srcY, + GLsizei width, GLsizei height, + GLenum intFormat, + GLenum filter) { + bool newTex; + _mesa_BindTexture(tex->Target, tex->TexObj); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + newTex = _mesa_meta_alloc_texture(tex, width, height, intFormat); /* copy framebuffer image to texture */ if (newTex) { @@ -1354,675 +1283,83 @@ setup_copypix_texture(struct gl_context *ctx, _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat, srcX, srcY, width, height, 0); } - else { - /* create empty texture */ - _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, - tex->Width, tex->Height, 0, - intFormat, GL_UNSIGNED_BYTE, NULL); - /* load image */ - _mesa_CopyTexSubImage2D(tex->Target, 0, - 0, 0, srcX, srcY, width, height); - } - } - else { - /* replace existing tex image */ - _mesa_CopyTexSubImage2D(tex->Target, 0, - 0, 0, srcX, srcY, width, height); - } -} - - -/** - * Setup/load texture for glDrawPixels. - */ -static void -setup_drawpix_texture(struct gl_context *ctx, - struct temp_texture *tex, - GLboolean newTex, - GLenum texIntFormat, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels) -{ - _mesa_BindTexture(tex->Target, tex->TexObj); - _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - /* copy pixel data to texture */ - if (newTex) { - /* create new tex image */ - if (tex->Width == width && tex->Height == height) { - /* create new tex and load image data */ - _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, - tex->Width, tex->Height, 0, format, type, pixels); - } - else { - struct gl_buffer_object *save_unpack_obj = NULL; - - _mesa_reference_buffer_object(ctx, &save_unpack_obj, - ctx->Unpack.BufferObj); - _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); - /* create empty texture */ - _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, - tex->Width, tex->Height, 0, format, type, NULL); - if (save_unpack_obj != NULL) - _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, - save_unpack_obj->Name); - /* load image */ - _mesa_TexSubImage2D(tex->Target, 0, - 0, 0, width, height, format, type, pixels); - } - } - else { - /* replace existing tex image */ - _mesa_TexSubImage2D(tex->Target, 0, - 0, 0, width, height, format, type, pixels); - } -} - - - -/** - * One-time init for drawing depth pixels. - */ -static void -init_blit_depth_pixels(struct gl_context *ctx) -{ - static const char *program = - "!!ARBfp1.0\n" - "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" - "END \n"; - char program2[200]; - struct blit_state *blit = &ctx->Meta->Blit; - struct temp_texture *tex = get_temp_texture(ctx); - const char *texTarget; - - assert(blit->DepthFP == 0); - - /* replace %s with "RECT" or "2D" */ - assert(strlen(program) + 4 < sizeof(program2)); - if (tex->Target == GL_TEXTURE_RECTANGLE) - texTarget = "RECT"; - else - texTarget = "2D"; - _mesa_snprintf(program2, sizeof(program2), program, texTarget); - - _mesa_GenProgramsARB(1, &blit->DepthFP); - _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); - _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(program2), (const GLubyte *) program2); -} - -static void -setup_ff_blit_framebuffer(struct blit_state *blit) -{ - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - - if (blit->VAO == 0) { - /* one-time setup */ - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &blit->VAO); - _mesa_BindVertexArray(blit->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &blit->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); - - /* setup vertex arrays */ - _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } - - /* setup projection matrix */ - _mesa_MatrixMode(GL_PROJECTION); - _mesa_LoadIdentity(); - _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); - -} - -static void -setup_glsl_blit_framebuffer(struct gl_context *ctx, - struct blit_state *blit, - GLenum target) -{ - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - const char *vs_source; - char *fs_source; - GLuint vs, fs; - void *mem_ctx; - GLuint ShaderProg; - GLboolean texture_2d = (target == GL_TEXTURE_2D); - - /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */ - assert(_mesa_is_desktop_gl(ctx) || texture_2d); - - /* Check if already initialized */ - if (blit->VAO == 0) { - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &blit->VAO); - _mesa_BindVertexArray(blit->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &blit->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); - - /* setup vertex arrays */ - _mesa_VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(x)); - _mesa_VertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(s)); - - _mesa_EnableVertexAttribArray(0); - _mesa_EnableVertexAttribArray(1); - } - - /* Generate a relevant fragment shader program for the texture target */ - if ((target == GL_TEXTURE_2D && blit->ShaderProg != 0) || - (target == GL_TEXTURE_RECTANGLE && blit->RectShaderProg != 0)) { - return; - } - - mem_ctx = ralloc_context(NULL); - - if (ctx->Const.GLSLVersion < 130) { - vs_source = - "attribute vec2 position;\n" - "attribute vec2 textureCoords;\n" - "varying vec2 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; - - fs_source = ralloc_asprintf(mem_ctx, - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "varying vec2 texCoords;\n" - "void main()\n" - "{\n" - " gl_FragColor = %s(texSampler, texCoords);\n" - " gl_FragDepth = gl_FragColor.r;\n" - "}\n", - texture_2d ? "sampler2D" : "sampler2DRect", - texture_2d ? "texture2D" : "texture2DRect"); - } - else { - vs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "in vec2 position;\n" - "in vec2 textureCoords;\n" - "out vec2 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); - fs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "in vec2 texCoords;\n" - "out vec4 out_color;\n" - "\n" - "void main()\n" - "{\n" - " out_color = %s(texSampler, texCoords);\n" - " gl_FragDepth = out_color.r;\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es", - texture_2d ? "sampler2D" : "sampler2DRect", - texture_2d ? "texture" : "texture2DRect"); - } - - vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); - fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); - - ShaderProg = _mesa_CreateProgramObjectARB(); - _mesa_AttachShader(ShaderProg, fs); - _mesa_DeleteObjectARB(fs); - _mesa_AttachShader(ShaderProg, vs); - _mesa_DeleteObjectARB(vs); - _mesa_BindAttribLocation(ShaderProg, 0, "position"); - _mesa_BindAttribLocation(ShaderProg, 1, "texcoords"); - link_program_with_debug(ctx, ShaderProg); - ralloc_free(mem_ctx); - if (texture_2d) - blit->ShaderProg = ShaderProg; - else - blit->RectShaderProg = ShaderProg; -} - -/** - * Try to do a glBlitFramebuffer using no-copy texturing. - * We can do this when the src renderbuffer is actually a texture. - * But if the src buffer == dst buffer we cannot do this. - * - * \return new buffer mask indicating the buffers left to blit using the - * normal path. - */ -static GLbitfield -blitframebuffer_texture(struct gl_context *ctx, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter, GLint flipX, - GLint flipY, GLboolean glsl_version) -{ - if (mask & GL_COLOR_BUFFER_BIT) { - const struct gl_framebuffer *drawFb = ctx->DrawBuffer; - const struct gl_framebuffer *readFb = ctx->ReadBuffer; - const struct gl_renderbuffer_attachment *drawAtt; - const struct gl_renderbuffer_attachment *readAtt = - &readFb->Attachment[readFb->_ColorReadBufferIndex]; - - if (readAtt && readAtt->Texture) { - struct blit_state *blit = &ctx->Meta->Blit; - const GLint dstX = MIN2(dstX0, dstX1); - const GLint dstY = MIN2(dstY0, dstY1); - const GLint dstW = abs(dstX1 - dstX0); - const GLint dstH = abs(dstY1 - dstY0); - const struct gl_texture_object *texObj = readAtt->Texture; - const GLuint srcLevel = readAtt->TextureLevel; - const GLint baseLevelSave = texObj->BaseLevel; - const GLint maxLevelSave = texObj->MaxLevel; - const GLenum target = texObj->Target; - GLuint sampler, samplerSave = - ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? - ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; - int i; - - /* Iterate through all draw buffers */ - for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; - if (idx == -1) - continue; - drawAtt = &drawFb->Attachment[idx]; - - if (drawAtt->Texture == readAtt->Texture) { - /* Can't use same texture as both the source and dest. We need - * to handle overlapping blits and besides, some hw may not - * support this. - */ - return mask; - } - } - - if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) { - /* Can't handle other texture types at this time */ - return mask; - } - - /* Choose between glsl version and fixed function version of - * BlitFramebuffer function. - */ - if (glsl_version) { - setup_glsl_blit_framebuffer(ctx, blit, target); - if (target == GL_TEXTURE_2D) - _mesa_UseProgram(blit->ShaderProg); - else - _mesa_UseProgram(blit->RectShaderProg); - } - else { - setup_ff_blit_framebuffer(&ctx->Meta->Blit); - } - - _mesa_BindVertexArray(blit->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - - _mesa_GenSamplers(1, &sampler); - _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); - - /* - printf("Blit from texture!\n"); - printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); - printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); - */ - - /* Prepare src texture state */ - _mesa_BindTexture(target, texObj->Name); - _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter); - _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter); - if (target != GL_TEXTURE_RECTANGLE_ARB) { - _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel); - _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); - } - _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - /* Always do our blits with no sRGB decode or encode. Note that - * GL_FRAMEBUFFER_SRGB has already been disabled by - * _mesa_meta_begin(). - */ - if (ctx->Extensions.EXT_texture_sRGB_decode) { - _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, - GL_SKIP_DECODE_EXT); - } - - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) { - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - _mesa_set_enable(ctx, target, GL_TRUE); - } - - /* Prepare vertex data (the VBO was previously created and bound) */ - { - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - GLfloat s0, t0, s1, t1; - - if (target == GL_TEXTURE_2D) { - const struct gl_texture_image *texImage - = _mesa_select_tex_image(ctx, texObj, target, srcLevel); - s0 = srcX0 / (float) texImage->Width; - s1 = srcX1 / (float) texImage->Width; - t0 = srcY0 / (float) texImage->Height; - t1 = srcY1 / (float) texImage->Height; - } - else { - assert(target == GL_TEXTURE_RECTANGLE_ARB); - s0 = (float) srcX0; - s1 = (float) srcX1; - t0 = (float) srcY0; - t1 = (float) srcY1; - } - - /* setup vertex positions */ - verts[0].x = -1.0F * flipX; - verts[0].y = -1.0F * flipY; - verts[1].x = 1.0F * flipX; - verts[1].y = -1.0F * flipY; - verts[2].x = 1.0F * flipX; - verts[2].y = 1.0F * flipY; - verts[3].x = -1.0F * flipX; - verts[3].y = 1.0F * flipY; - - verts[0].s = s0; - verts[0].t = t0; - verts[1].s = s1; - verts[1].t = t0; - verts[2].s = s1; - verts[2].t = t1; - verts[3].s = s0; - verts[3].t = t1; - - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); - } - - /* setup viewport */ - _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); - _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - _mesa_DepthMask(GL_FALSE); - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); - - /* Restore texture object state, the texture binding will - * be restored by _mesa_meta_end(). - */ - if (target != GL_TEXTURE_RECTANGLE_ARB) { - _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); - _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); - } - - _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); - _mesa_DeleteSamplers(1, &sampler); - - /* Done with color buffer */ - mask &= ~GL_COLOR_BUFFER_BIT; - } - } - - return mask; -} - - -/** - * Meta implementation of ctx->Driver.BlitFramebuffer() in terms - * of texture mapping and polygon rendering. - */ -void -_mesa_meta_BlitFramebuffer(struct gl_context *ctx, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - struct blit_state *blit = &ctx->Meta->Blit; - struct temp_texture *tex = get_temp_texture(ctx); - struct temp_texture *depthTex = get_temp_depth_texture(ctx); - const GLsizei maxTexSize = tex->MaxSize; - const GLint srcX = MIN2(srcX0, srcX1); - const GLint srcY = MIN2(srcY0, srcY1); - const GLint srcW = abs(srcX1 - srcX0); - const GLint srcH = abs(srcY1 - srcY0); - const GLint dstX = MIN2(dstX0, dstX1); - const GLint dstY = MIN2(dstY0, dstY1); - const GLint dstW = abs(dstX1 - dstX0); - const GLint dstH = abs(dstY1 - dstY0); - const GLint srcFlipX = (srcX1 - srcX0) / srcW; - const GLint srcFlipY = (srcY1 - srcY0) / srcH; - const GLint dstFlipX = (dstX1 - dstX0) / dstW; - const GLint dstFlipY = (dstY1 - dstY0) / dstH; - const GLint flipX = srcFlipX * dstFlipX; - const GLint flipY = srcFlipY * dstFlipY; - - struct vertex { - GLfloat x, y, s, t; - }; - struct vertex verts[4]; - GLboolean newTex; - const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && - ctx->Extensions.ARB_fragment_shader && - (ctx->API != API_OPENGLES); - - /* In addition to falling back if the blit size is larger than the maximum - * texture size, fallback if the source is multisampled. This fallback can - * be removed once Mesa gets support ARB_texture_multisample. - */ - if (srcW > maxTexSize || srcH > maxTexSize - || ctx->ReadBuffer->Visual.samples > 0) { - /* XXX avoid this fallback */ - _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter); - return; - } - - /* only scissor effects blit so save/clear all other relevant state */ - _mesa_meta_begin(ctx, ~MESA_META_SCISSOR); - - /* Try faster, direct texture approach first */ - mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - dstFlipX, dstFlipY, use_glsl_version); - if (mask == 0x0) { - _mesa_meta_end(ctx); - return; - } - - /* Choose between glsl version and fixed function version of - * BlitFramebuffer function. - */ - if (use_glsl_version) { - setup_glsl_blit_framebuffer(ctx, blit, tex->Target); - if (tex->Target == GL_TEXTURE_2D) - _mesa_UseProgram(blit->ShaderProg); - else - _mesa_UseProgram(blit->RectShaderProg); + else { + /* create empty texture */ + _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, + tex->Width, tex->Height, 0, + intFormat, GL_UNSIGNED_BYTE, NULL); + /* load image */ + _mesa_CopyTexSubImage2D(tex->Target, 0, + 0, 0, srcX, srcY, width, height); + } } else { - setup_ff_blit_framebuffer(blit); - } - - _mesa_BindVertexArray(blit->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - - /* Continue with "normal" approach which involves copying the src rect - * into a temporary texture and is "blitted" by drawing a textured quad. - */ - { - /* setup vertex positions */ - verts[0].x = -1.0F * flipX; - verts[0].y = -1.0F * flipY; - verts[1].x = 1.0F * flipX; - verts[1].y = -1.0F * flipY; - verts[2].x = 1.0F * flipX; - verts[2].y = 1.0F * flipY; - verts[3].x = -1.0F * flipX; - verts[3].y = 1.0F * flipY; - + /* replace existing tex image */ + _mesa_CopyTexSubImage2D(tex->Target, 0, + 0, 0, srcX, srcY, width, height); } +} - /* glEnable() in gles2 and gles3 doesn't allow GL_TEXTURE_{1D, 2D, etc.} - * tokens. - */ - if (_mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES) - _mesa_set_enable(ctx, tex->Target, GL_TRUE); - if (mask & GL_COLOR_BUFFER_BIT) { - const struct gl_framebuffer *readFb = ctx->ReadBuffer; - const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; - const GLenum rb_base_format = - _mesa_base_tex_format(ctx, colorReadRb->InternalFormat); +/** + * Setup/load texture for glDrawPixels. + */ +void +_mesa_meta_setup_drawpix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLboolean newTex, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels) +{ + _mesa_BindTexture(tex->Target, tex->TexObj); + _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - /* Using the exact source rectangle to create the texture does incorrect - * linear filtering along the edges. So, allocate the texture extended along - * edges by one pixel in x, y directions. - */ - newTex = alloc_texture(tex, srcW + 2, srcH + 2, rb_base_format); - setup_copypix_texture(ctx, tex, newTex, - srcX - 1, srcY - 1, srcW + 2, srcH + 2, - rb_base_format, filter); - /* texcoords (after texture allocation!) */ - { - verts[0].s = 1.0F; - verts[0].t = 1.0F; - verts[1].s = tex->Sright - 1.0F; - verts[1].t = 1.0F; - verts[2].s = tex->Sright - 1.0F; - verts[2].t = tex->Ttop - 1.0F; - verts[3].s = 1.0F; - verts[3].t = tex->Ttop - 1.0F; - - /* upload new vertex data */ - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + /* copy pixel data to texture */ + if (newTex) { + /* create new tex image */ + if (tex->Width == width && tex->Height == height) { + /* create new tex and load image data */ + _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, + tex->Width, tex->Height, 0, format, type, pixels); } + else { + struct gl_buffer_object *save_unpack_obj = NULL; - _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); - _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); - _mesa_DepthMask(GL_FALSE); - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); - mask &= ~GL_COLOR_BUFFER_BIT; - } - - if ((mask & GL_DEPTH_BUFFER_BIT) && - _mesa_is_desktop_gl(ctx) && - ctx->Extensions.ARB_depth_texture && - ctx->Extensions.ARB_fragment_program) { - - GLuint *tmp = malloc(srcW * srcH * sizeof(GLuint)); - - if (tmp) { - - newTex = alloc_texture(depthTex, srcW, srcH, GL_DEPTH_COMPONENT); - _mesa_ReadPixels(srcX, srcY, srcW, srcH, GL_DEPTH_COMPONENT, - GL_UNSIGNED_INT, tmp); - setup_drawpix_texture(ctx, depthTex, newTex, GL_DEPTH_COMPONENT, - srcW, srcH, GL_DEPTH_COMPONENT, - GL_UNSIGNED_INT, tmp); - - /* texcoords (after texture allocation!) */ - { - verts[0].s = 0.0F; - verts[0].t = 0.0F; - verts[1].s = depthTex->Sright; - verts[1].t = 0.0F; - verts[2].s = depthTex->Sright; - verts[2].t = depthTex->Ttop; - verts[3].s = 0.0F; - verts[3].t = depthTex->Ttop; - - /* upload new vertex data */ - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); - } - - if (!blit->DepthFP) - init_blit_depth_pixels(ctx); - - _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); - _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); - _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); - _mesa_DepthFunc(GL_ALWAYS); - _mesa_DepthMask(GL_TRUE); - - _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); - mask &= ~GL_DEPTH_BUFFER_BIT; - - free(tmp); + _mesa_reference_buffer_object(ctx, &save_unpack_obj, + ctx->Unpack.BufferObj); + _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); + /* create empty texture */ + _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, + tex->Width, tex->Height, 0, format, type, NULL); + if (save_unpack_obj != NULL) + _mesa_BindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, + save_unpack_obj->Name); + /* load image */ + _mesa_TexSubImage2D(tex->Target, 0, + 0, 0, width, height, format, type, pixels); } } - - if (mask & GL_STENCIL_BUFFER_BIT) { - /* XXX can't easily do stencil */ - } - - if (_mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES) - _mesa_set_enable(ctx, tex->Target, GL_FALSE); - - _mesa_meta_end(ctx); - - if (mask) { - _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter); + else { + /* replace existing tex image */ + _mesa_TexSubImage2D(tex->Target, 0, + 0, 0, width, height, format, type, pixels); } } -static void -meta_glsl_blit_cleanup(struct blit_state *blit) +void +_mesa_meta_setup_ff_tnl_for_blit(GLuint *VAO, GLuint *VBO, + unsigned texcoord_size) { - if (blit->VAO) { - _mesa_DeleteVertexArrays(1, &blit->VAO); - blit->VAO = 0; - _mesa_DeleteBuffers(1, &blit->VBO); - blit->VBO = 0; - } - if (blit->DepthFP) { - _mesa_DeleteProgramsARB(1, &blit->DepthFP); - blit->DepthFP = 0; - } - - _mesa_DeleteObjectARB(blit->ShaderProg); - blit->ShaderProg = 0; - _mesa_DeleteObjectARB(blit->RectShaderProg); - blit->RectShaderProg = 0; + _mesa_meta_setup_vertex_objects(VAO, VBO, false, 2, texcoord_size, 0); - _mesa_DeleteTextures(1, &blit->depthTex.TexObj); - blit->depthTex.TexObj = 0; + /* setup projection matrix */ + _mesa_MatrixMode(GL_PROJECTION); + _mesa_LoadIdentity(); } - /** * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. */ @@ -2030,9 +1367,6 @@ void _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) { struct clear_state *clear = &ctx->Meta->Clear; - struct vertex { - GLfloat x, y, z, r, g, b, a; - }; struct vertex verts[4]; /* save all state but scissor, pixel pack/unpack */ GLbitfield metaSave = (MESA_META_ALL - @@ -2049,27 +1383,7 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) _mesa_meta_begin(ctx, metaSave); - if (clear->VAO == 0) { - /* one-time setup */ - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &clear->VAO); - _mesa_BindVertexArray(clear->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &clear->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); - - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_COLOR_ARRAY); - } - else { - _mesa_BindVertexArray(clear->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); - } + _mesa_meta_setup_vertex_objects(&clear->VAO, &clear->VBO, false, 3, 0, 4); /* GL_COLOR_BUFFER_BIT */ if (buffers & BUFFER_BITS_COLOR) { @@ -2171,9 +1485,6 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) " }\n" "}\n"; const char *fs_source = - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" "uniform vec4 color;\n" "void main()\n" "{\n" @@ -2182,20 +1493,10 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) GLuint vs, gs = 0, fs; bool has_integer_textures; - if (clear->VAO != 0) - return; - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &clear->VAO); - _mesa_BindVertexArray(clear->VAO); + _mesa_meta_setup_vertex_objects(&clear->VAO, &clear->VBO, true, 3, 0, 0); - /* create vertex array buffer */ - _mesa_GenBuffers(1, &clear->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); - - /* setup vertex arrays */ - _mesa_VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - _mesa_EnableVertexAttribArray(0); + if (clear->ShaderProg != 0) + return; vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER); _mesa_ShaderSource(vs, 1, &vs_source, NULL); @@ -2235,30 +1536,27 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) void *shader_source_mem_ctx = ralloc_context(NULL); const char *vs_int_source = ralloc_asprintf(shader_source_mem_ctx, - "#version %s\n" + "#version 130\n" "in vec4 position;\n" "void main()\n" "{\n" " gl_Position = position;\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); + "}\n"); const char *fs_int_source = ralloc_asprintf(shader_source_mem_ctx, - "#version %s\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" + "#version 130\n" "uniform ivec4 color;\n" "out ivec4 out_color;\n" "\n" "void main()\n" "{\n" " out_color = color;\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); + "}\n"); - vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source); - fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source); + vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER, + vs_int_source); + fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, + fs_int_source); ralloc_free(shader_source_mem_ctx); clear->IntegerShaderProg = _mesa_CreateProgramObjectARB(); @@ -2275,7 +1573,9 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) * BindFragDataLocation to 0. */ - link_program_with_debug(ctx, clear->IntegerShaderProg); + _mesa_ObjectLabel(GL_PROGRAM, clear->IntegerShaderProg, -1, + "integer clear"); + _mesa_meta_link_program_with_debug(ctx, clear->IntegerShaderProg); clear->IntegerColorLocation = _mesa_GetUniformLocation(clear->IntegerShaderProg, "color"); @@ -2321,9 +1621,7 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) const float x1 = ((float)fb->_Xmax / fb->Width) * 2.0f - 1.0f; const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0f - 1.0f; const float z = -invert_z(ctx->Depth.Clear); - struct vertex { - GLfloat x, y, z; - } verts[4]; + struct vertex verts[4]; metaSave = (MESA_META_ALPHA_TEST | MESA_META_BLEND | @@ -2359,9 +1657,6 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) ctx->Color.ClearColor.f); } - _mesa_BindVertexArray(clear->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO); - /* GL_COLOR_BUFFER_BIT */ if (buffers & BUFFER_BITS_COLOR) { /* leave colormask, glDrawBuffer state as-is */ @@ -2443,13 +1738,8 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, GLint dstX, GLint dstY, GLenum type) { struct copypix_state *copypix = &ctx->Meta->CopyPix; - struct temp_texture *tex = get_temp_texture(ctx); - struct vertex { - GLfloat x, y, z, s, t; - }; + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); struct vertex verts[4]; - GLboolean newTex; - GLenum intFormat = GL_RGBA; if (type != GL_COLOR || ctx->_ImageTransferState || @@ -2472,31 +1762,15 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, MESA_META_VERTEX | MESA_META_VIEWPORT)); - if (copypix->VAO == 0) { - /* one-time setup */ - - /* create vertex array object */ - _mesa_GenVertexArrays(1, ©pix->VAO); - _mesa_BindVertexArray(copypix->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, ©pix->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, copypix->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); + _mesa_meta_setup_vertex_objects(©pix->VAO, ©pix->VBO, false, + 3, 2, 0); - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } - else { - _mesa_BindVertexArray(copypix->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, copypix->VBO); - } + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); - newTex = alloc_texture(tex, width, height, intFormat); + /* Alloc/setup texture */ + _mesa_meta_setup_copypix_texture(ctx, tex, srcX, srcY, width, height, + GL_RGBA, GL_NEAREST); /* vertex positions, texcoords (after texture allocation!) */ { @@ -2509,32 +1783,28 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, verts[0].x = dstX0; verts[0].y = dstY0; verts[0].z = z; - verts[0].s = 0.0F; - verts[0].t = 0.0F; + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; verts[1].x = dstX1; verts[1].y = dstY0; verts[1].z = z; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; + verts[1].tex[0] = tex->Sright; + verts[1].tex[1] = 0.0F; verts[2].x = dstX1; verts[2].y = dstY1; verts[2].z = z; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; + verts[2].tex[0] = tex->Sright; + verts[2].tex[1] = tex->Ttop; verts[3].x = dstX0; verts[3].y = dstY1; verts[3].z = z; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = tex->Ttop; /* upload new vertex data */ _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); } - /* Alloc/setup texture */ - setup_copypix_texture(ctx, tex, newTex, srcX, srcY, width, height, - GL_RGBA, GL_NEAREST); - _mesa_set_enable(ctx, tex->Target, GL_TRUE); /* draw textured quad */ @@ -2551,6 +1821,9 @@ meta_drawpix_cleanup(struct drawpix_state *drawpix) if (drawpix->VAO != 0) { _mesa_DeleteVertexArrays(1, &drawpix->VAO); drawpix->VAO = 0; + + _mesa_DeleteBuffers(1, &drawpix->VBO); + drawpix->VBO = 0; } if (drawpix->StencilFP != 0) { @@ -2646,7 +1919,7 @@ init_draw_stencil_pixels(struct gl_context *ctx) "END \n"; char program2[1000]; struct drawpix_state *drawpix = &ctx->Meta->DrawPix; - struct temp_texture *tex = get_temp_texture(ctx); + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); const char *texTarget; assert(drawpix->StencilFP == 0); @@ -2680,7 +1953,7 @@ init_draw_depth_pixels(struct gl_context *ctx) "END \n"; char program2[200]; struct drawpix_state *drawpix = &ctx->Meta->DrawPix; - struct temp_texture *tex = get_temp_texture(ctx); + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); const char *texTarget; assert(drawpix->DepthFP == 0); @@ -2712,17 +1985,13 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, const GLvoid *pixels) { struct drawpix_state *drawpix = &ctx->Meta->DrawPix; - struct temp_texture *tex = get_temp_texture(ctx); + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); const struct gl_pixelstore_attrib unpackSave = ctx->Unpack; const GLuint origStencilMask = ctx->Stencil.WriteMask[0]; - struct vertex { - GLfloat x, y, z, s, t; - }; struct vertex verts[4]; GLenum texIntFormat; GLboolean fallback, newTex; GLbitfield metaExtraSave = 0x0; - GLuint vbo; /* * Determine if we can do the glDrawPixels with texture mapping. @@ -2812,7 +2081,13 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, MESA_META_VIEWPORT | metaExtraSave)); - newTex = alloc_texture(tex, width, height, texIntFormat); + newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat); + + _mesa_meta_setup_vertex_objects(&drawpix->VAO, &drawpix->VBO, false, + 3, 2, 0); + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); /* vertex positions, texcoords (after texture allocation!) */ { @@ -2825,43 +2100,29 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, verts[0].x = x0; verts[0].y = y0; verts[0].z = z; - verts[0].s = 0.0F; - verts[0].t = 0.0F; + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; verts[1].x = x1; verts[1].y = y0; verts[1].z = z; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; + verts[1].tex[0] = tex->Sright; + verts[1].tex[1] = 0.0F; verts[2].x = x1; verts[2].y = y1; verts[2].z = z; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; + verts[2].tex[0] = tex->Sright; + verts[2].tex[1] = tex->Ttop; verts[3].x = x0; verts[3].y = y1; verts[3].z = z; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; - } - - if (drawpix->VAO == 0) { - /* one-time setup: create vertex array object */ - _mesa_GenVertexArrays(1, &drawpix->VAO); + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = tex->Ttop; } - _mesa_BindVertexArray(drawpix->VAO); - /* create vertex array buffer */ - _mesa_GenBuffers(1, &vbo); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, vbo); + /* upload new vertex data */ _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, GL_DYNAMIC_DRAW_ARB); - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - /* set given unpack params */ ctx->Unpack = *unpack; @@ -2874,8 +2135,8 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, if (!drawpix->StencilFP) init_draw_stencil_pixels(ctx); - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - GL_ALPHA, type, pixels); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + GL_ALPHA, type, pixels); _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -2917,22 +2178,20 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, ctx->Current.RasterColor); - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - format, type, pixels); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + format, type, pixels); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } else { /* Drawing RGBA */ - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - format, type, pixels); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + format, type, pixels); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } _mesa_set_enable(ctx, tex->Target, GL_FALSE); - _mesa_DeleteBuffers(1, &vbo); - /* restore unpack params */ ctx->Unpack = unpackSave; @@ -2984,9 +2243,6 @@ _mesa_meta_Bitmap(struct gl_context *ctx, const GLenum texIntFormat = GL_ALPHA; const struct gl_pixelstore_attrib unpackSave = *unpack; GLubyte fg, bg; - struct vertex { - GLfloat x, y, z, s, t, r, g, b, a; - }; struct vertex verts[4]; GLboolean newTex; GLubyte *bitmap8; @@ -3020,33 +2276,12 @@ _mesa_meta_Bitmap(struct gl_context *ctx, MESA_META_VERTEX | MESA_META_VIEWPORT)); - if (bitmap->VAO == 0) { - /* one-time setup */ - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &bitmap->VAO); - _mesa_BindVertexArray(bitmap->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &bitmap->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, bitmap->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); + _mesa_meta_setup_vertex_objects(&bitmap->VAO, &bitmap->VBO, false, 3, 2, 4); - /* setup vertex arrays */ - _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); - _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - _mesa_EnableClientState(GL_COLOR_ARRAY); - } - else { - _mesa_BindVertexArray(bitmap->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, bitmap->VBO); - } + newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat); - newTex = alloc_texture(tex, width, height, texIntFormat); + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); /* vertex positions, texcoords, colors (after texture allocation!) */ { @@ -3060,23 +2295,23 @@ _mesa_meta_Bitmap(struct gl_context *ctx, verts[0].x = x0; verts[0].y = y0; verts[0].z = z; - verts[0].s = 0.0F; - verts[0].t = 0.0F; + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; verts[1].x = x1; verts[1].y = y0; verts[1].z = z; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; + verts[1].tex[0] = tex->Sright; + verts[1].tex[1] = 0.0F; verts[2].x = x1; verts[2].y = y1; verts[2].z = z; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; + verts[2].tex[0] = tex->Sright; + verts[2].tex[1] = tex->Ttop; verts[3].x = x0; verts[3].y = y1; verts[3].z = z; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = tex->Ttop; for (i = 0; i < 4; i++) { verts[i].r = ctx->Current.RasterColor[0]; @@ -3110,8 +2345,8 @@ _mesa_meta_Bitmap(struct gl_context *ctx, _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE); _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg)); - setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, - GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8); + _mesa_meta_setup_drawpix_texture(ctx, tex, newTex, width, height, + GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -3236,10 +2471,10 @@ setup_texture_coords(GLenum faceTarget, GLint width, GLint height, GLint depth, - GLfloat coords0[3], - GLfloat coords1[3], - GLfloat coords2[3], - GLfloat coords3[3]) + GLfloat coords0[4], + GLfloat coords1[4], + GLfloat coords2[4], + GLfloat coords3[4]) { static const GLfloat st[4][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} @@ -3247,6 +2482,13 @@ setup_texture_coords(GLenum faceTarget, GLuint i; GLfloat r; + /* Currently all texture targets want the W component to be 1.0. + */ + coords0[3] = 1.0F; + coords1[3] = 1.0F; + coords2[3] = 1.0F; + coords3[3] = 1.0F; + switch (faceTarget) { case GL_TEXTURE_1D: case GL_TEXTURE_2D: @@ -3337,6 +2579,8 @@ setup_texture_coords(GLenum faceTarget, assert(0); } + coord[3] = (float) (slice / 6); + switch (faceTarget) { case GL_TEXTURE_CUBE_MAP_POSITIVE_X: coord[0] = 1.0f; @@ -3378,74 +2622,53 @@ setup_texture_coords(GLenum faceTarget, } } - -static void -setup_ff_generate_mipmap(struct gen_mipmap_state *mipmap) -{ - struct vertex { - GLfloat x, y, tex[3]; - }; - - if (mipmap->VAO == 0) { - /* one-time setup */ - /* create vertex array object */ - _mesa_GenVertexArrays(1, &mipmap->VAO); - _mesa_BindVertexArray(mipmap->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &mipmap->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, mipmap->VBO); - /* setup vertex arrays */ - _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } - - /* setup projection matrix */ - _mesa_MatrixMode(GL_PROJECTION); - _mesa_LoadIdentity(); - _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); -} - - -static struct glsl_sampler * -setup_texture_sampler(GLenum target, struct gen_mipmap_state *mipmap) +static struct blit_shader * +choose_blit_shader(GLenum target, struct blit_shader_table *table) { switch(target) { case GL_TEXTURE_1D: - mipmap->sampler_1d.type = "sampler1D"; - mipmap->sampler_1d.func = "texture1D"; - mipmap->sampler_1d.texcoords = "texCoords.x"; - return &mipmap->sampler_1d; + table->sampler_1d.type = "sampler1D"; + table->sampler_1d.func = "texture1D"; + table->sampler_1d.texcoords = "texCoords.x"; + return &table->sampler_1d; case GL_TEXTURE_2D: - mipmap->sampler_2d.type = "sampler2D"; - mipmap->sampler_2d.func = "texture2D"; - mipmap->sampler_2d.texcoords = "texCoords.xy"; - return &mipmap->sampler_2d; + table->sampler_2d.type = "sampler2D"; + table->sampler_2d.func = "texture2D"; + table->sampler_2d.texcoords = "texCoords.xy"; + return &table->sampler_2d; + case GL_TEXTURE_RECTANGLE: + table->sampler_rect.type = "sampler2DRect"; + table->sampler_rect.func = "texture2DRect"; + table->sampler_rect.texcoords = "texCoords.xy"; + return &table->sampler_rect; case GL_TEXTURE_3D: /* Code for mipmap generation with 3D textures is not used yet. * It's a sw fallback. */ - mipmap->sampler_3d.type = "sampler3D"; - mipmap->sampler_3d.func = "texture3D"; - mipmap->sampler_3d.texcoords = "texCoords"; - return &mipmap->sampler_3d; + table->sampler_3d.type = "sampler3D"; + table->sampler_3d.func = "texture3D"; + table->sampler_3d.texcoords = "texCoords.xyz"; + return &table->sampler_3d; case GL_TEXTURE_CUBE_MAP: - mipmap->sampler_cubemap.type = "samplerCube"; - mipmap->sampler_cubemap.func = "textureCube"; - mipmap->sampler_cubemap.texcoords = "texCoords"; - return &mipmap->sampler_cubemap; + table->sampler_cubemap.type = "samplerCube"; + table->sampler_cubemap.func = "textureCube"; + table->sampler_cubemap.texcoords = "texCoords.xyz"; + return &table->sampler_cubemap; case GL_TEXTURE_1D_ARRAY: - mipmap->sampler_1d_array.type = "sampler1DArray"; - mipmap->sampler_1d_array.func = "texture1DArray"; - mipmap->sampler_1d_array.texcoords = "texCoords.xy"; - return &mipmap->sampler_1d_array; + table->sampler_1d_array.type = "sampler1DArray"; + table->sampler_1d_array.func = "texture1DArray"; + table->sampler_1d_array.texcoords = "texCoords.xy"; + return &table->sampler_1d_array; case GL_TEXTURE_2D_ARRAY: - mipmap->sampler_2d_array.type = "sampler2DArray"; - mipmap->sampler_2d_array.func = "texture2DArray"; - mipmap->sampler_2d_array.texcoords = "texCoords"; - return &mipmap->sampler_2d_array; + table->sampler_2d_array.type = "sampler2DArray"; + table->sampler_2d_array.func = "texture2DArray"; + table->sampler_2d_array.texcoords = "texCoords.xyz"; + return &table->sampler_2d_array; + case GL_TEXTURE_CUBE_MAP_ARRAY: + table->sampler_cubemap_array.type = "samplerCubeArray"; + table->sampler_cubemap_array.func = "textureCubeArray"; + table->sampler_cubemap_array.texcoords = "texCoords.xyzw"; + return &table->sampler_cubemap_array; default: _mesa_problem(NULL, "Unexpected texture target 0x%x in" " setup_texture_sampler()\n", target); @@ -3453,122 +2676,28 @@ setup_texture_sampler(GLenum target, struct gen_mipmap_state *mipmap) } } - -static void -setup_glsl_generate_mipmap(struct gl_context *ctx, - struct gen_mipmap_state *mipmap, - GLenum target) +void +_mesa_meta_blit_shader_table_cleanup(struct blit_shader_table *table) { - struct vertex { - GLfloat x, y, tex[3]; - }; - struct glsl_sampler *sampler; - const char *vs_source; - char *fs_source; - GLuint vs, fs; - void *mem_ctx; - - /* Check if already initialized */ - if (mipmap->VAO == 0) { - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &mipmap->VAO); - _mesa_BindVertexArray(mipmap->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &mipmap->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, mipmap->VBO); - - /* setup vertex arrays */ - _mesa_VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(x)); - _mesa_VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, - sizeof(struct vertex), OFFSET(tex)); - _mesa_EnableVertexAttribArray(0); - _mesa_EnableVertexAttribArray(1); - } - - /* Generate a fragment shader program appropriate for the texture target */ - sampler = setup_texture_sampler(target, mipmap); - assert(sampler != NULL); - if (sampler->shader_prog != 0) { - mipmap->ShaderProg = sampler->shader_prog; - return; - } - - mem_ctx = ralloc_context(NULL); - - if (ctx->API == API_OPENGLES2 || ctx->Const.GLSLVersion < 130) { - vs_source = - "attribute vec2 position;\n" - "attribute vec3 textureCoords;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; - - fs_source = ralloc_asprintf(mem_ctx, - "#extension GL_EXT_texture_array : enable\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "varying vec3 texCoords;\n" - "void main()\n" - "{\n" - " gl_FragColor = %s(texSampler, %s);\n" - "}\n", - sampler->type, - sampler->func, sampler->texcoords); - } - else { - vs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "in vec2 position;\n" - "in vec3 textureCoords;\n" - "out vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); - fs_source = ralloc_asprintf(mem_ctx, - "#version %s\n" - "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif\n" - "uniform %s texSampler;\n" - "in vec3 texCoords;\n" - "out vec4 out_color;\n" - "\n" - "void main()\n" - "{\n" - " out_color = texture(texSampler, %s);\n" - "}\n", - _mesa_is_desktop_gl(ctx) ? "130" : "300 es", - sampler->type, - sampler->texcoords); - } - - vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); - fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); - - mipmap->ShaderProg = _mesa_CreateProgramObjectARB(); - _mesa_AttachShader(mipmap->ShaderProg, fs); - _mesa_DeleteObjectARB(fs); - _mesa_AttachShader(mipmap->ShaderProg, vs); - _mesa_DeleteObjectARB(vs); - _mesa_BindAttribLocation(mipmap->ShaderProg, 0, "position"); - _mesa_BindAttribLocation(mipmap->ShaderProg, 1, "texcoords"); - link_program_with_debug(ctx, mipmap->ShaderProg); - sampler->shader_prog = mipmap->ShaderProg; - ralloc_free(mem_ctx); + _mesa_DeleteObjectARB(table->sampler_1d.shader_prog); + _mesa_DeleteObjectARB(table->sampler_2d.shader_prog); + _mesa_DeleteObjectARB(table->sampler_3d.shader_prog); + _mesa_DeleteObjectARB(table->sampler_rect.shader_prog); + _mesa_DeleteObjectARB(table->sampler_cubemap.shader_prog); + _mesa_DeleteObjectARB(table->sampler_1d_array.shader_prog); + _mesa_DeleteObjectARB(table->sampler_2d_array.shader_prog); + _mesa_DeleteObjectARB(table->sampler_cubemap_array.shader_prog); + + table->sampler_1d.shader_prog = 0; + table->sampler_2d.shader_prog = 0; + table->sampler_3d.shader_prog = 0; + table->sampler_rect.shader_prog = 0; + table->sampler_cubemap.shader_prog = 0; + table->sampler_1d_array.shader_prog = 0; + table->sampler_2d_array.shader_prog = 0; + table->sampler_cubemap_array.shader_prog = 0; } - static void meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap) { @@ -3579,19 +2708,7 @@ meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap) _mesa_DeleteBuffers(1, &mipmap->VBO); mipmap->VBO = 0; - _mesa_DeleteObjectARB(mipmap->sampler_1d.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_2d.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_3d.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_cubemap.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_1d_array.shader_prog); - _mesa_DeleteObjectARB(mipmap->sampler_2d_array.shader_prog); - - mipmap->sampler_1d.shader_prog = 0; - mipmap->sampler_2d.shader_prog = 0; - mipmap->sampler_3d.shader_prog = 0; - mipmap->sampler_cubemap.shader_prog = 0; - mipmap->sampler_1d_array.shader_prog = 0; - mipmap->sampler_2d_array.shader_prog = 0; + _mesa_meta_blit_shader_table_cleanup(&mipmap->shaders); } @@ -3605,9 +2722,6 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, struct gl_texture_object *texObj) { struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; - struct vertex { - GLfloat x, y, tex[3]; - }; struct vertex verts[4]; const GLuint baseLevel = texObj->BaseLevel; const GLuint maxLevel = texObj->MaxLevel; @@ -3616,8 +2730,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, const GLuint fboSave = ctx->DrawBuffer->Name; const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit; const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && - ctx->Extensions.ARB_fragment_shader && - (ctx->API != API_OPENGLES); + ctx->Extensions.ARB_fragment_shader; GLenum faceTarget; GLuint dstLevel; const GLint slice = 0; @@ -3643,17 +2756,15 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, * GenerateMipmap function. */ if (use_glsl_version) { - setup_glsl_generate_mipmap(ctx, mipmap, target); - _mesa_UseProgram(mipmap->ShaderProg); + _mesa_meta_setup_vertex_objects(&mipmap->VAO, &mipmap->VBO, true, + 2, 3, 0); + _mesa_meta_setup_blit_shader(ctx, target, &mipmap->shaders); } else { - setup_ff_generate_mipmap(mipmap); + _mesa_meta_setup_ff_tnl_for_blit(&mipmap->VAO, &mipmap->VBO, 3); _mesa_set_enable(ctx, target, GL_TRUE); } - _mesa_BindVertexArray(mipmap->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, mipmap->VBO); - samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; @@ -3691,10 +2802,10 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO); - if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) - _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); - else - assert(!genMipmapSave); + _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); /* Setup texture coordinates */ setup_texture_coords(faceTarget, @@ -3895,6 +3006,12 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, GLint bpp; void *buf; + /* The gl_renderbuffer is part of the interface for + * dd_function_table::CopyTexSubImage, but this implementation does not use + * it. + */ + (void) rb; + /* Choose format/type for temporary image buffer */ format = _mesa_get_format_base_format(texImage->TexFormat); if (format == GL_LUMINANCE || @@ -4004,17 +3121,17 @@ decompress_texture_image(struct gl_context *ctx, const GLint depth = texImage->Height; const GLenum target = texObj->Target; GLenum faceTarget; - struct vertex { - GLfloat x, y, tex[3]; - }; struct vertex verts[4]; GLuint fboDrawSave, fboReadSave; GLuint rbSave; GLuint samplerSave; + const bool use_glsl_version = ctx->Extensions.ARB_vertex_shader && + ctx->Extensions.ARB_fragment_shader; if (slice > 0) { assert(target == GL_TEXTURE_3D || - target == GL_TEXTURE_2D_ARRAY); + target == GL_TEXTURE_2D_ARRAY || + target == GL_TEXTURE_CUBE_MAP_ARRAY); } switch (target) { @@ -4027,10 +3144,9 @@ decompress_texture_image(struct gl_context *ctx, assert(!"No compressed 3D textures."); return; - case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_CUBE_MAP_ARRAY: - /* These targets are just broken currently. */ - return; + faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + (slice % 6); + break; case GL_TEXTURE_CUBE_MAP: faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; @@ -4075,27 +3191,13 @@ decompress_texture_image(struct gl_context *ctx, decompress->Height = height; } - /* setup VBO data */ - if (decompress->VAO == 0) { - /* create vertex array object */ - _mesa_GenVertexArrays(1, &decompress->VAO); - _mesa_BindVertexArray(decompress->VAO); - - /* create vertex array buffer */ - _mesa_GenBuffers(1, &decompress->VBO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, decompress->VBO); - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), - NULL, GL_DYNAMIC_DRAW_ARB); + if (use_glsl_version) { + _mesa_meta_setup_vertex_objects(&decompress->VAO, &decompress->VBO, true, + 2, 4, 0); - /* setup vertex arrays */ - _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); - _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); - _mesa_EnableClientState(GL_VERTEX_ARRAY); - _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); - } - else { - _mesa_BindVertexArray(decompress->VAO); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, decompress->VBO); + _mesa_meta_setup_blit_shader(ctx, target, &decompress->shaders); + } else { + _mesa_meta_setup_ff_tnl_for_blit(&decompress->VAO, &decompress->VBO, 3); } if (!decompress->Sampler) { @@ -4114,6 +3216,9 @@ decompress_texture_image(struct gl_context *ctx, _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler); } + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); + setup_texture_coords(faceTarget, slice, width, height, depth, verts[0].tex, verts[1].tex, @@ -4130,8 +3235,6 @@ decompress_texture_image(struct gl_context *ctx, verts[3].x = -1.0F; verts[3].y = 1.0F; - _mesa_MatrixMode(GL_PROJECTION); - _mesa_LoadIdentity(); _mesa_set_viewport(ctx, 0, 0, 0, width, height); /* upload new vertex data */ @@ -4139,7 +3242,9 @@ decompress_texture_image(struct gl_context *ctx, /* setup texture state */ _mesa_BindTexture(target, texObj->Name); - _mesa_set_enable(ctx, target, GL_TRUE); + + if (!use_glsl_version) + _mesa_set_enable(ctx, target, GL_TRUE); { /* save texture object state */ @@ -4199,7 +3304,8 @@ decompress_texture_image(struct gl_context *ctx, } /* disable texture unit */ - _mesa_set_enable(ctx, target, GL_FALSE); + if (!use_glsl_version) + _mesa_set_enable(ctx, target, GL_FALSE); _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); @@ -4231,8 +3337,7 @@ _mesa_meta_GetTexImage(struct gl_context *ctx, * unsigned, normalized values. We could handle signed and unnormalized * with floating point renderbuffers... */ - if (texImage->TexObject->Target != GL_TEXTURE_CUBE_MAP_ARRAY - && _mesa_is_format_compressed(texImage->TexFormat) && + if (_mesa_is_format_compressed(texImage->TexFormat) && _mesa_get_format_datatype(texImage->TexFormat) == GL_UNSIGNED_NORMALIZED) { struct gl_texture_object *texObj = texImage->TexObject; @@ -4241,7 +3346,8 @@ _mesa_meta_GetTexImage(struct gl_context *ctx, _mesa_unlock_texture(ctx, texObj); for (slice = 0; slice < texImage->Depth; slice++) { void *dst; - if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) { + if (texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY + || texImage->TexObject->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { /* Setup pixel packing. SkipPixels and SkipRows will be applied * in the decompress_texture_image() function's call to * glReadPixels but we need to compute the dest slice's address diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index 53d7b8ab5..fcf45c403 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -60,6 +60,311 @@ #define MESA_META_OCCLUSION_QUERY 0x400000 /**\}*/ +/** + * State which we may save/restore across meta ops. + * XXX this may be incomplete... + */ +struct save_state +{ + GLbitfield SavedState; /**< bitmask of MESA_META_* flags */ + + /* Always saved/restored with meta. */ + gl_api API; + + /** MESA_META_CLEAR (and others?) */ + struct gl_query_object *CurrentOcclusionObject; + + /** MESA_META_ALPHA_TEST */ + GLboolean AlphaEnabled; + GLenum AlphaFunc; + GLclampf AlphaRef; + + /** MESA_META_BLEND */ + GLbitfield BlendEnabled; + GLboolean ColorLogicOpEnabled; + + /** MESA_META_COLOR_MASK */ + GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; + + /** MESA_META_DEPTH_TEST */ + struct gl_depthbuffer_attrib Depth; + + /** MESA_META_FOG */ + GLboolean Fog; + + /** MESA_META_PIXEL_STORE */ + struct gl_pixelstore_attrib Pack, Unpack; + + /** MESA_META_PIXEL_TRANSFER */ + GLfloat RedBias, RedScale; + GLfloat GreenBias, GreenScale; + GLfloat BlueBias, BlueScale; + GLfloat AlphaBias, AlphaScale; + GLfloat DepthBias, DepthScale; + GLboolean MapColorFlag; + + /** MESA_META_RASTERIZATION */ + GLenum FrontPolygonMode, BackPolygonMode; + GLboolean PolygonOffset; + GLboolean PolygonSmooth; + GLboolean PolygonStipple; + GLboolean PolygonCull; + + /** MESA_META_SCISSOR */ + struct gl_scissor_attrib Scissor; + + /** MESA_META_SHADER */ + GLboolean VertexProgramEnabled; + struct gl_vertex_program *VertexProgram; + GLboolean FragmentProgramEnabled; + struct gl_fragment_program *FragmentProgram; + GLboolean ATIFragmentShaderEnabled; + struct gl_shader_program *Shader[MESA_SHADER_STAGES]; + struct gl_shader_program *ActiveShader; + + /** MESA_META_STENCIL_TEST */ + struct gl_stencil_attrib Stencil; + + /** MESA_META_TRANSFORM */ + GLenum MatrixMode; + GLfloat ModelviewMatrix[16]; + GLfloat ProjectionMatrix[16]; + GLfloat TextureMatrix[16]; + + /** MESA_META_CLIP */ + GLbitfield ClipPlanesEnabled; + + /** MESA_META_TEXTURE */ + GLuint ActiveUnit; + GLuint ClientActiveUnit; + /** for unit[0] only */ + struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS]; + /** mask of TEXTURE_2D_BIT, etc */ + GLbitfield TexEnabled[MAX_TEXTURE_UNITS]; + GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS]; + GLuint EnvMode; /* unit[0] only */ + + /** MESA_META_VERTEX */ + struct gl_vertex_array_object *VAO; + struct gl_buffer_object *ArrayBufferObj; + + /** MESA_META_VIEWPORT */ + GLfloat ViewportX, ViewportY, ViewportW, ViewportH; + GLclampd DepthNear, DepthFar; + + /** MESA_META_CLAMP_FRAGMENT_COLOR */ + GLenum ClampFragmentColor; + + /** MESA_META_CLAMP_VERTEX_COLOR */ + GLenum ClampVertexColor; + + /** MESA_META_CONDITIONAL_RENDER */ + struct gl_query_object *CondRenderQuery; + GLenum CondRenderMode; + + /** MESA_META_SELECT_FEEDBACK */ + GLenum RenderMode; + struct gl_selection Select; + struct gl_feedback Feedback; + + /** MESA_META_MULTISAMPLE */ + struct gl_multisample_attrib Multisample; + + /** MESA_META_FRAMEBUFFER_SRGB */ + GLboolean sRGBEnabled; + + /** Miscellaneous (always disabled) */ + GLboolean Lighting; + GLboolean RasterDiscard; + GLboolean TransformFeedbackNeedsResume; +}; + +/** + * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc. + * This is currently shared by all the meta ops. But we could create a + * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc. + */ +struct temp_texture +{ + GLuint TexObj; + GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */ + GLsizei MinSize; /**< Min texture size to allocate */ + GLsizei MaxSize; /**< Max possible texture size */ + GLboolean NPOT; /**< Non-power of two size OK? */ + GLsizei Width, Height; /**< Current texture size */ + GLenum IntFormat; + GLfloat Sright, Ttop; /**< right, top texcoords */ +}; + +/** + * State for GLSL texture sampler which is used to generate fragment + * shader in _mesa_meta_generate_mipmap(). + */ +struct blit_shader { + const char *type; + const char *func; + const char *texcoords; + GLuint shader_prog; +}; + +/** + * Table of all sampler types and shaders for accessing them. + */ +struct blit_shader_table { + struct blit_shader sampler_1d; + struct blit_shader sampler_2d; + struct blit_shader sampler_3d; + struct blit_shader sampler_rect; + struct blit_shader sampler_cubemap; + struct blit_shader sampler_1d_array; + struct blit_shader sampler_2d_array; + struct blit_shader sampler_cubemap_array; +}; + +/** + * Indices in the blit_state->msaa_shaders[] array + * + * Note that setup_glsl_msaa_blit_shader() assumes that the _INT enums are one + * more than the non-_INT version and _UINT is one beyond that. + */ +enum blit_msaa_shader { + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_INT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_UINT, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE, + BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY, + BLIT_MSAA_SHADER_COUNT, +}; + +/** + * State for glBlitFramebufer() + */ +struct blit_state +{ + GLuint VAO; + GLuint VBO; + GLuint DepthFP; + struct blit_shader_table shaders; + GLuint msaa_shaders[BLIT_MSAA_SHADER_COUNT]; + struct temp_texture depthTex; +}; + + +/** + * State for glClear() + */ +struct clear_state +{ + GLuint VAO; + GLuint VBO; + GLuint ShaderProg; + GLint ColorLocation; + GLint LayerLocation; + + GLuint IntegerShaderProg; + GLint IntegerColorLocation; + GLint IntegerLayerLocation; +}; + + +/** + * State for glCopyPixels() + */ +struct copypix_state +{ + GLuint VAO; + GLuint VBO; +}; + + +/** + * State for glDrawPixels() + */ +struct drawpix_state +{ + GLuint VAO; + GLuint VBO; + + GLuint StencilFP; /**< Fragment program for drawing stencil images */ + GLuint DepthFP; /**< Fragment program for drawing depth images */ +}; + + +/** + * State for glBitmap() + */ +struct bitmap_state +{ + GLuint VAO; + GLuint VBO; + struct temp_texture Tex; /**< separate texture from other meta ops */ +}; + +/** + * State for _mesa_meta_generate_mipmap() + */ +struct gen_mipmap_state +{ + GLuint VAO; + GLuint VBO; + GLuint FBO; + GLuint Sampler; + + struct blit_shader_table shaders; +}; + +/** + * State for texture decompression + */ +struct decompress_state +{ + GLuint VAO; + GLuint VBO, FBO, RBO, Sampler; + GLint Width, Height; + + struct blit_shader_table shaders; +}; + +/** + * State for glDrawTex() + */ +struct drawtex_state +{ + GLuint VAO; + GLuint VBO; +}; + +#define MAX_META_OPS_DEPTH 8 +/** + * All per-context meta state. + */ +struct gl_meta_state +{ + /** Stack of state saved during meta-ops */ + struct save_state Save[MAX_META_OPS_DEPTH]; + /** Save stack depth */ + GLuint SaveStackDepth; + + struct temp_texture TempTex; + + struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */ + struct clear_state Clear; /**< For _mesa_meta_Clear() */ + struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */ + struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */ + struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */ + struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */ + struct decompress_state Decompress; /**< For texture decompression */ + struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */ +}; + +struct vertex { + GLfloat x, y, z, tex[4]; + GLfloat r, g, b, a; +}; + extern void _mesa_meta_init(struct gl_context *ctx); @@ -130,4 +435,60 @@ extern void _mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); +/* meta-internal functions */ +GLuint +_mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target, + const GLcharARB *source); + + +GLuint +_mesa_meta_link_program_with_debug(struct gl_context *ctx, GLuint program); + +GLboolean +_mesa_meta_alloc_texture(struct temp_texture *tex, + GLsizei width, GLsizei height, GLenum intFormat); + +struct temp_texture * +_mesa_meta_get_temp_texture(struct gl_context *ctx); + +struct temp_texture * +_mesa_meta_get_temp_depth_texture(struct gl_context *ctx); + +void +_mesa_meta_setup_vertex_objects(GLuint *VAO, GLuint *VBO, + bool use_generic_attributes, + unsigned vertex_size, unsigned texcoord_size, + unsigned color_size); + +void +_mesa_meta_setup_ff_tnl_for_blit(GLuint *VAO, GLuint *VBO, + unsigned texcoord_size); + +void +_mesa_meta_setup_drawpix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLboolean newTex, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels); + +void +_mesa_meta_setup_copypix_texture(struct gl_context *ctx, + struct temp_texture *tex, + GLint srcX, GLint srcY, + GLsizei width, GLsizei height, + GLenum intFormat, + GLenum filter); + +void +_mesa_meta_setup_blit_shader(struct gl_context *ctx, + GLenum target, + struct blit_shader_table *table); + +void +_mesa_meta_glsl_blit_cleanup(struct blit_state *blit); + +void +_mesa_meta_blit_shader_table_cleanup(struct blit_shader_table *table); + #endif /* META_H */ diff --git a/mesalib/src/mesa/drivers/common/meta_blit.c b/mesalib/src/mesa/drivers/common/meta_blit.c new file mode 100644 index 000000000..907c2cdf3 --- /dev/null +++ b/mesalib/src/mesa/drivers/common/meta_blit.c @@ -0,0 +1,825 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2009 VMware, Inc. 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, 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 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. + */ + +#include "main/glheader.h" +#include "main/mtypes.h" +#include "main/imports.h" +#include "main/arbprogram.h" +#include "main/arrayobj.h" +#include "main/blend.h" +#include "main/condrender.h" +#include "main/depth.h" +#include "main/enable.h" +#include "main/enums.h" +#include "main/fbobject.h" +#include "main/macros.h" +#include "main/matrix.h" +#include "main/multisample.h" +#include "main/objectlabel.h" +#include "main/readpix.h" +#include "main/shaderapi.h" +#include "main/texobj.h" +#include "main/texenv.h" +#include "main/teximage.h" +#include "main/texparam.h" +#include "main/varray.h" +#include "main/viewport.h" +#include "swrast/swrast.h" +#include "drivers/common/meta.h" +#include "../glsl/ralloc.h" + +/** Return offset in bytes of the field within a vertex struct */ +#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) + +/** + * One-time init for drawing depth pixels. + */ +static void +init_blit_depth_pixels(struct gl_context *ctx) +{ + static const char *program = + "!!ARBfp1.0\n" + "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" + "END \n"; + char program2[200]; + struct blit_state *blit = &ctx->Meta->Blit; + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); + const char *texTarget; + + assert(blit->DepthFP == 0); + + /* replace %s with "RECT" or "2D" */ + assert(strlen(program) + 4 < sizeof(program2)); + if (tex->Target == GL_TEXTURE_RECTANGLE) + texTarget = "RECT"; + else + texTarget = "2D"; + _mesa_snprintf(program2, sizeof(program2), program, texTarget); + + _mesa_GenProgramsARB(1, &blit->DepthFP); + _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); + _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(program2), (const GLubyte *) program2); +} + +static void +setup_glsl_msaa_blit_shader(struct gl_context *ctx, + struct blit_state *blit, + struct gl_renderbuffer *src_rb, + GLenum target) +{ + const char *vs_source; + char *fs_source; + GLuint vs, fs; + void *mem_ctx; + enum blit_msaa_shader shader_index; + bool dst_is_msaa = false; + GLenum src_datatype; + const char *vec4_prefix; + char *name; + + if (src_rb) { + src_datatype = _mesa_get_format_datatype(src_rb->Format); + } else { + /* depth-or-color glCopyTexImage fallback path that passes a NULL rb and + * doesn't handle integer. + */ + src_datatype = GL_UNSIGNED_NORMALIZED; + } + + if (ctx->DrawBuffer->Visual.samples > 1) { + /* If you're calling meta_BlitFramebuffer with the destination + * multisampled, this is the only path that will work -- swrast and + * CopyTexImage won't work on it either. + */ + assert(ctx->Extensions.ARB_sample_shading); + + dst_is_msaa = true; + + /* We need shader invocation per sample, not per pixel */ + _mesa_set_enable(ctx, GL_MULTISAMPLE, GL_TRUE); + _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_TRUE); + _mesa_MinSampleShading(1.0); + } + + switch (target) { + case GL_TEXTURE_2D_MULTISAMPLE: + if (src_rb->_BaseFormat == GL_DEPTH_COMPONENT || + src_rb->_BaseFormat == GL_DEPTH_STENCIL) { + if (dst_is_msaa) + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY; + else + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE; + } else { + if (dst_is_msaa) + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY; + else + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE; + } + break; + default: + _mesa_problem(ctx, "Unkown texture target %s\n", + _mesa_lookup_enum_by_nr(target)); + shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE; + } + + /* We rely on the enum being sorted this way. */ + STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT == + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 1); + STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT == + BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 2); + if (src_datatype == GL_INT) { + shader_index++; + vec4_prefix = "i"; + } else if (src_datatype == GL_UNSIGNED_INT) { + shader_index += 2; + vec4_prefix = "u"; + } else { + vec4_prefix = ""; + } + + if (blit->msaa_shaders[shader_index]) { + _mesa_UseProgram(blit->msaa_shaders[shader_index]); + return; + } + + mem_ctx = ralloc_context(NULL); + + if (shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE || + shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY) { + char *sample_index; + const char *arb_sample_shading_extension_string; + + if (dst_is_msaa) { + arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable"; + sample_index = "gl_SampleID"; + name = "depth MSAA copy"; + } else { + /* Don't need that extension, since we're drawing to a single-sampled + * destination. + */ + arb_sample_shading_extension_string = ""; + /* From the GL 4.3 spec: + * + * "If there is a multisample buffer (the value of SAMPLE_BUFFERS + * is one), then values are obtained from the depth samples in + * this buffer. It is recommended that the depth value of the + * centermost sample be used, though implementations may choose + * any function of the depth sample values at each pixel. + * + * We're slacking and instead of choosing centermost, we've got 0. + */ + sample_index = "0"; + name = "depth MSAA resolve"; + } + + vs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "in vec2 position;\n" + "in vec2 textureCoords;\n" + "out vec2 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"); + fs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "#extension GL_ARB_texture_multisample : enable\n" + "%s\n" + "uniform sampler2DMS texSampler;\n" + "in vec2 texCoords;\n" + "out vec4 out_color;\n" + "\n" + "void main()\n" + "{\n" + " gl_FragDepth = texelFetch(texSampler, ivec2(texCoords), %s).r;\n" + "}\n", + arb_sample_shading_extension_string, + sample_index); + } else { + /* You can create 2D_MULTISAMPLE textures with 0 sample count (meaning 1 + * sample). Yes, this is ridiculous. + */ + int samples; + char *sample_resolve; + const char *arb_sample_shading_extension_string; + const char *merge_function; + name = ralloc_asprintf(mem_ctx, "%svec4 MSAA %s", + vec4_prefix, + dst_is_msaa ? "copy" : "resolve"); + + samples = MAX2(src_rb->NumSamples, 1); + + if (dst_is_msaa) { + arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable"; + sample_resolve = ralloc_asprintf(mem_ctx, " out_color = texelFetch(texSampler, ivec2(texCoords), gl_SampleID);"); + merge_function = ""; + } else { + int i; + int step; + + if (src_datatype == GL_INT || src_datatype == GL_UNSIGNED_INT) { + merge_function = + "gvec4 merge(gvec4 a, gvec4 b) { return (a >> gvec4(1)) + (b >> gvec4(1)) + (a & b & gvec4(1)); }\n"; + } else { + /* The divide will happen at the end for floats. */ + merge_function = + "vec4 merge(vec4 a, vec4 b) { return (a + b); }\n"; + } + + arb_sample_shading_extension_string = ""; + + /* We're assuming power of two samples for this resolution procedure. + * + * To avoid losing any floating point precision if the samples all + * happen to have the same value, we merge pairs of values at a time + * (so the floating point exponent just gets increased), rather than + * doing a naive sum and dividing. + */ + assert((samples & (samples - 1)) == 0); + /* Fetch each individual sample. */ + sample_resolve = rzalloc_size(mem_ctx, 1); + for (i = 0; i < samples; i++) { + ralloc_asprintf_append(&sample_resolve, + " gvec4 sample_1_%d = texelFetch(texSampler, ivec2(texCoords), %d);\n", + i, i); + } + /* Now, merge each pair of samples, then merge each pair of those, + * etc. + */ + for (step = 2; step <= samples; step *= 2) { + for (i = 0; i < samples; i += step) { + ralloc_asprintf_append(&sample_resolve, + " gvec4 sample_%d_%d = merge(sample_%d_%d, sample_%d_%d);\n", + step, i, + step / 2, i, + step / 2, i + step / 2); + } + } + + /* Scale the final result. */ + if (src_datatype == GL_UNSIGNED_INT || src_datatype == GL_INT) { + ralloc_asprintf_append(&sample_resolve, + " out_color = sample_%d_0;\n", + samples); + } else { + ralloc_asprintf_append(&sample_resolve, + " out_color = sample_%d_0 / %f;\n", + samples, (float)samples); + } + } + + vs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "in vec2 position;\n" + "in vec2 textureCoords;\n" + "out vec2 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n"); + fs_source = ralloc_asprintf(mem_ctx, + "#version 130\n" + "#extension GL_ARB_texture_multisample : enable\n" + "%s\n" + "#define gvec4 %svec4\n" + "uniform %ssampler2DMS texSampler;\n" + "in vec2 texCoords;\n" + "out gvec4 out_color;\n" + "\n" + "%s" /* merge_function */ + "void main()\n" + "{\n" + "%s\n" /* sample_resolve */ + "}\n", + arb_sample_shading_extension_string, + vec4_prefix, + vec4_prefix, + merge_function, + sample_resolve); + } + + vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); + fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); + + blit->msaa_shaders[shader_index] = _mesa_CreateProgramObjectARB(); + _mesa_AttachShader(blit->msaa_shaders[shader_index], fs); + _mesa_DeleteObjectARB(fs); + _mesa_AttachShader(blit->msaa_shaders[shader_index], vs); + _mesa_DeleteObjectARB(vs); + _mesa_BindAttribLocation(blit->msaa_shaders[shader_index], 0, "position"); + _mesa_BindAttribLocation(blit->msaa_shaders[shader_index], 1, "texcoords"); + _mesa_meta_link_program_with_debug(ctx, blit->msaa_shaders[shader_index]); + _mesa_ObjectLabel(GL_PROGRAM, blit->msaa_shaders[shader_index], -1, name); + ralloc_free(mem_ctx); + + _mesa_UseProgram(blit->msaa_shaders[shader_index]); +} + +static void +setup_glsl_blit_framebuffer(struct gl_context *ctx, + struct blit_state *blit, + struct gl_renderbuffer *src_rb, + GLenum target) +{ + /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */ + assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D); + + _mesa_meta_setup_vertex_objects(&blit->VAO, &blit->VBO, true, 2, 2, 0); + + if (target == GL_TEXTURE_2D_MULTISAMPLE) { + setup_glsl_msaa_blit_shader(ctx, blit, src_rb, target); + } else { + _mesa_meta_setup_blit_shader(ctx, target, &blit->shaders); + } +} + +/** + * Try to do a color or depth glBlitFramebuffer using texturing. + * + * We can do this when the src renderbuffer is actually a texture, or when the + * driver exposes BindRenderbufferTexImage(). + */ +static bool +blitframebuffer_texture(struct gl_context *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLenum filter, GLint flipX, GLint flipY, + GLboolean glsl_version, GLboolean do_depth) +{ + const struct gl_framebuffer *readFb = ctx->ReadBuffer; + int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex; + const struct gl_renderbuffer_attachment *readAtt = + &readFb->Attachment[att_index]; + struct blit_state *blit = &ctx->Meta->Blit; + const GLint dstX = MIN2(dstX0, dstX1); + const GLint dstY = MIN2(dstY0, dstY1); + const GLint dstW = abs(dstX1 - dstX0); + const GLint dstH = abs(dstY1 - dstY0); + struct gl_texture_object *texObj; + GLuint srcLevel; + GLint baseLevelSave; + GLint maxLevelSave; + GLenum target; + GLuint sampler, samplerSave = + ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? + ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; + GLuint tempTex = 0; + struct gl_renderbuffer *rb = readAtt->Renderbuffer; + + if (rb->NumSamples && !ctx->Extensions.ARB_texture_multisample) + return false; + + if (filter == GL_SCALED_RESOLVE_FASTEST_EXT || + filter == GL_SCALED_RESOLVE_NICEST_EXT) { + filter = GL_LINEAR; + } + + if (readAtt->Texture) { + /* If there's a texture attached of a type we can handle, then just use + * it directly. + */ + srcLevel = readAtt->TextureLevel; + texObj = readAtt->Texture; + target = texObj->Target; + + switch (target) { + case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE: + case GL_TEXTURE_2D_MULTISAMPLE: + break; + default: + return false; + } + } else if (ctx->Driver.BindRenderbufferTexImage) { + /* Otherwise, we need the driver to be able to bind a renderbuffer as + * a texture image. + */ + struct gl_texture_image *texImage; + + if (rb->NumSamples > 1) + target = GL_TEXTURE_2D_MULTISAMPLE; + else + target = GL_TEXTURE_2D; + + _mesa_GenTextures(1, &tempTex); + _mesa_BindTexture(target, tempTex); + srcLevel = 0; + texObj = _mesa_lookup_texture(ctx, tempTex); + texImage = _mesa_get_tex_image(ctx, texObj, target, srcLevel); + + if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) { + _mesa_DeleteTextures(1, &tempTex); + return false; + } else { + if (ctx->Driver.FinishRenderTexture && + !rb->NeedsFinishRenderTexture) { + rb->NeedsFinishRenderTexture = true; + ctx->Driver.FinishRenderTexture(ctx, rb); + } + + if (_mesa_is_winsys_fbo(readFb)) { + GLint temp = srcY0; + srcY0 = rb->Height - srcY1; + srcY1 = rb->Height - temp; + flipY = -flipY; + } + } + } else { + return false; + } + + baseLevelSave = texObj->BaseLevel; + maxLevelSave = texObj->MaxLevel; + + if (glsl_version) { + setup_glsl_blit_framebuffer(ctx, blit, rb, target); + } + else { + _mesa_meta_setup_ff_tnl_for_blit(&ctx->Meta->Blit.VAO, + &ctx->Meta->Blit.VBO, + 2); + } + + _mesa_GenSamplers(1, &sampler); + _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); + + /* + printf("Blit from texture!\n"); + printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); + printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); + */ + + /* Prepare src texture state */ + _mesa_BindTexture(target, texObj->Name); + _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter); + _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter); + if (target != GL_TEXTURE_RECTANGLE_ARB) { + _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel); + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); + } + _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + /* Always do our blits with no net sRGB decode or encode. + * + * However, if both the src and dst can be srgb decode/encoded, enable them + * so that we do any blending (from scaling or from MSAA resolves) in the + * right colorspace. + * + * Our choice of not doing any net encode/decode is from the GL 3.0 + * specification: + * + * "Blit operations bypass the fragment pipeline. The only fragment + * operations which affect a blit are the pixel ownership test and the + * scissor test." + * + * The GL 4.4 specification disagrees and says that the sRGB part of the + * fragment pipeline applies, but this was found to break applications. + */ + if (ctx->Extensions.EXT_texture_sRGB_decode) { + if (_mesa_get_format_color_encoding(rb->Format) == GL_SRGB && + ctx->DrawBuffer->Visual.sRGBCapable) { + _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, + GL_DECODE_EXT); + _mesa_set_framebuffer_srgb(ctx, GL_TRUE); + } else { + _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, + GL_SKIP_DECODE_EXT); + /* set_framebuffer_srgb was set by _mesa_meta_begin(). */ + } + } + + if (!glsl_version) { + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + _mesa_set_enable(ctx, target, GL_TRUE); + } + + /* Prepare vertex data (the VBO was previously created and bound) */ + { + struct vertex verts[4]; + GLfloat s0, t0, s1, t1; + + if (target == GL_TEXTURE_2D) { + const struct gl_texture_image *texImage + = _mesa_select_tex_image(ctx, texObj, target, srcLevel); + s0 = srcX0 / (float) texImage->Width; + s1 = srcX1 / (float) texImage->Width; + t0 = srcY0 / (float) texImage->Height; + t1 = srcY1 / (float) texImage->Height; + } + else { + assert(target == GL_TEXTURE_RECTANGLE_ARB || + target == GL_TEXTURE_2D_MULTISAMPLE); + s0 = (float) srcX0; + s1 = (float) srcX1; + t0 = (float) srcY0; + t1 = (float) srcY1; + } + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); + + /* setup vertex positions */ + verts[0].x = -1.0F * flipX; + verts[0].y = -1.0F * flipY; + verts[1].x = 1.0F * flipX; + verts[1].y = -1.0F * flipY; + verts[2].x = 1.0F * flipX; + verts[2].y = 1.0F * flipY; + verts[3].x = -1.0F * flipX; + verts[3].y = 1.0F * flipY; + + verts[0].tex[0] = s0; + verts[0].tex[1] = t0; + verts[1].tex[0] = s1; + verts[1].tex[1] = t0; + verts[2].tex[0] = s1; + verts[2].tex[1] = t1; + verts[3].tex[0] = s0; + verts[3].tex[1] = t1; + + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + } + + /* setup viewport */ + _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); + _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth); + _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth); + _mesa_DepthMask(do_depth); + _mesa_DepthFunc(GL_ALWAYS); + + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + + /* Restore texture object state, the texture binding will + * be restored by _mesa_meta_end(). + */ + if (target != GL_TEXTURE_RECTANGLE_ARB) { + _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); + } + + _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); + _mesa_DeleteSamplers(1, &sampler); + if (tempTex) + _mesa_DeleteTextures(1, &tempTex); + + return true; +} + +/** + * Meta implementation of ctx->Driver.BlitFramebuffer() in terms + * of texture mapping and polygon rendering. + */ +void +_mesa_meta_BlitFramebuffer(struct gl_context *ctx, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + struct blit_state *blit = &ctx->Meta->Blit; + struct temp_texture *tex = _mesa_meta_get_temp_texture(ctx); + struct temp_texture *depthTex = _mesa_meta_get_temp_depth_texture(ctx); + const GLsizei maxTexSize = tex->MaxSize; + const GLint srcX = MIN2(srcX0, srcX1); + const GLint srcY = MIN2(srcY0, srcY1); + const GLint srcW = abs(srcX1 - srcX0); + const GLint srcH = abs(srcY1 - srcY0); + const GLint dstX = MIN2(dstX0, dstX1); + const GLint dstY = MIN2(dstY0, dstY1); + const GLint dstW = abs(dstX1 - dstX0); + const GLint dstH = abs(dstY1 - dstY0); + const GLint srcFlipX = (srcX1 - srcX0) / srcW; + const GLint srcFlipY = (srcY1 - srcY0) / srcH; + const GLint dstFlipX = (dstX1 - dstX0) / dstW; + const GLint dstFlipY = (dstY1 - dstY0) / dstH; + const GLint flipX = srcFlipX * dstFlipX; + const GLint flipY = srcFlipY * dstFlipY; + + struct vertex verts[4]; + GLboolean newTex; + const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && + ctx->Extensions.ARB_fragment_shader; + + /* In addition to falling back if the blit size is larger than the maximum + * texture size, fallback if the source is multisampled. This fallback can + * be removed once Mesa gets support ARB_texture_multisample. + */ + if (srcW > maxTexSize || srcH > maxTexSize) { + /* XXX avoid this fallback */ + goto fallback; + } + + /* Multisample texture blit support requires texture multisample. */ + if (ctx->ReadBuffer->Visual.samples > 0 && + !ctx->Extensions.ARB_texture_multisample) { + goto fallback; + } + + /* only scissor effects blit so save/clear all other relevant state */ + _mesa_meta_begin(ctx, ~MESA_META_SCISSOR); + + /* Try faster, direct texture approach first */ + if (mask & GL_COLOR_BUFFER_BIT) { + if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + filter, dstFlipX, dstFlipY, + use_glsl_version, false)) { + mask &= ~GL_COLOR_BUFFER_BIT; + if (mask == 0x0) { + _mesa_meta_end(ctx); + return; + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) { + if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + filter, dstFlipX, dstFlipY, + use_glsl_version, true)) { + mask &= ~GL_DEPTH_BUFFER_BIT; + if (mask == 0x0) { + _mesa_meta_end(ctx); + return; + } + } + } + + /* Choose between glsl version and fixed function version of + * BlitFramebuffer function. + */ + if (use_glsl_version) { + setup_glsl_blit_framebuffer(ctx, blit, NULL, tex->Target); + } + else { + _mesa_meta_setup_ff_tnl_for_blit(&blit->VAO, &blit->VBO, 2); + } + + /* Silence valgrind warnings about reading uninitialized stack. */ + memset(verts, 0, sizeof(verts)); + + /* Continue with "normal" approach which involves copying the src rect + * into a temporary texture and is "blitted" by drawing a textured quad. + */ + { + /* setup vertex positions */ + verts[0].x = -1.0F * flipX; + verts[0].y = -1.0F * flipY; + verts[1].x = 1.0F * flipX; + verts[1].y = -1.0F * flipY; + verts[2].x = 1.0F * flipX; + verts[2].y = 1.0F * flipY; + verts[3].x = -1.0F * flipX; + verts[3].y = 1.0F * flipY; + + } + + if (!use_glsl_version) + _mesa_set_enable(ctx, tex->Target, GL_TRUE); + + if (mask & GL_COLOR_BUFFER_BIT) { + const struct gl_framebuffer *readFb = ctx->ReadBuffer; + const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; + const GLenum rb_base_format = + _mesa_base_tex_format(ctx, colorReadRb->InternalFormat); + + /* Using the exact source rectangle to create the texture does incorrect + * linear filtering along the edges. So, allocate the texture extended along + * edges by one pixel in x, y directions. + */ + _mesa_meta_setup_copypix_texture(ctx, tex, + srcX - 1, srcY - 1, srcW + 2, srcH + 2, + rb_base_format, filter); + /* texcoords (after texture allocation!) */ + { + verts[0].tex[0] = 1.0F; + verts[0].tex[1] = 1.0F; + verts[1].tex[0] = tex->Sright - 1.0F; + verts[1].tex[1] = 1.0F; + verts[2].tex[0] = tex->Sright - 1.0F; + verts[2].tex[1] = tex->Ttop - 1.0F; + verts[3].tex[0] = 1.0F; + verts[3].tex[1] = tex->Ttop - 1.0F; + + /* upload new vertex data */ + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + } + + _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); + _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); + _mesa_DepthMask(GL_FALSE); + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + mask &= ~GL_COLOR_BUFFER_BIT; + } + + if ((mask & GL_DEPTH_BUFFER_BIT) && + _mesa_is_desktop_gl(ctx) && + ctx->Extensions.ARB_depth_texture && + ctx->Extensions.ARB_fragment_program) { + + GLuint *tmp = malloc(srcW * srcH * sizeof(GLuint)); + + if (tmp) { + + newTex = _mesa_meta_alloc_texture(depthTex, srcW, srcH, + GL_DEPTH_COMPONENT); + _mesa_ReadPixels(srcX, srcY, srcW, srcH, GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, tmp); + _mesa_meta_setup_drawpix_texture(ctx, depthTex, newTex, + srcW, srcH, GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, tmp); + + /* texcoords (after texture allocation!) */ + { + verts[0].tex[0] = 0.0F; + verts[0].tex[1] = 0.0F; + verts[1].tex[0] = depthTex->Sright; + verts[1].tex[1] = 0.0F; + verts[2].tex[0] = depthTex->Sright; + verts[2].tex[1] = depthTex->Ttop; + verts[3].tex[0] = 0.0F; + verts[3].tex[1] = depthTex->Ttop; + + /* upload new vertex data */ + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + } + + if (!blit->DepthFP) + init_blit_depth_pixels(ctx); + + _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); + _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); + _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); + _mesa_DepthFunc(GL_ALWAYS); + _mesa_DepthMask(GL_TRUE); + + _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); + mask &= ~GL_DEPTH_BUFFER_BIT; + + free(tmp); + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) { + /* XXX can't easily do stencil */ + } + + if (!use_glsl_version) + _mesa_set_enable(ctx, tex->Target, GL_FALSE); + + _mesa_meta_end(ctx); + +fallback: + if (mask) { + _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); + } +} + +void +_mesa_meta_glsl_blit_cleanup(struct blit_state *blit) +{ + if (blit->VAO) { + _mesa_DeleteVertexArrays(1, &blit->VAO); + blit->VAO = 0; + _mesa_DeleteBuffers(1, &blit->VBO); + blit->VBO = 0; + } + if (blit->DepthFP) { + _mesa_DeleteProgramsARB(1, &blit->DepthFP); + blit->DepthFP = 0; + } + + _mesa_meta_blit_shader_table_cleanup(&blit->shaders); + + _mesa_DeleteTextures(1, &blit->depthTex.TexObj); + blit->depthTex.TexObj = 0; +} diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 83841def5..aed73c73f 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -49,6 +49,7 @@ #include "../glsl/glsl_parser_extras.h" #include "main/mtypes.h" #include "main/version.h" +#include "main/errors.h" #include "main/macros.h" PUBLIC const char __dri2ConfigOptions[] = @@ -448,8 +449,11 @@ driContextSetFlags(struct gl_context *ctx, uint32_t flags) if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->DebugOutput = GL_TRUE; + } ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; - ctx->Debug.DebugOutput = GL_TRUE; } } @@ -764,12 +768,13 @@ const __DRIdri2Extension driDRI2Extension = { }; const __DRIswrastExtension driSWRastExtension = { - { __DRI_SWRAST, 4 }, - driSWRastCreateNewScreen, - driCreateNewDrawable, - driCreateNewContextForAPI, - driCreateContextAttribs, - driSWRastCreateNewScreen2, + .base = { __DRI_SWRAST, 4 }, + + .createNewScreen = driSWRastCreateNewScreen, + .createNewDrawable = driCreateNewDrawable, + .createNewContextForAPI = driCreateNewContextForAPI, + .createContextAttribs = driCreateContextAttribs, + .createNewScreen2 = driSWRastCreateNewScreen2, }; const __DRI2configQueryExtension dri2ConfigQueryExtension = { @@ -869,7 +874,7 @@ driImageFormatToGLFormat(uint32_t image_format) /** Image driver interface */ const __DRIimageDriverExtension driImageDriverExtension = { - .base = { __DRI_IMAGE_DRIVER, __DRI_IMAGE_DRIVER_VERSION }, + .base = { __DRI_IMAGE_DRIVER, 1 }, .createNewScreen2 = driCreateNewScreen2, .createNewDrawable = driCreateNewDrawable, @@ -888,6 +893,7 @@ static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y, /* for swrast only */ const __DRIcopySubBufferExtension driCopySubBufferExtension = { - { __DRI_COPY_SUB_BUFFER, 1 }, - .copySubBuffer = driCopySubBuffer, + .base = { __DRI_COPY_SUB_BUFFER, 1 }, + + .copySubBuffer = driCopySubBuffer, }; diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c index 29a57c8e5..05cbc0f1f 100644 --- a/mesalib/src/mesa/main/api_arrayelt.c +++ b/mesalib/src/mesa/main/api_arrayelt.c @@ -1458,7 +1458,8 @@ _ae_destroy_context(struct gl_context *ctx) static void check_vbo(AEcontext *actx, struct gl_buffer_object *vbo) { - if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) { + if (_mesa_is_bufferobj(vbo) && + !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) { GLuint i; for (i = 0; i < actx->nr_vbos; i++) if (actx->vbo[i] == vbo) @@ -1633,7 +1634,8 @@ _ae_map_vbos(struct gl_context *ctx) ctx->Driver.MapBufferRange(ctx, 0, actx->vbo[i]->Size, GL_MAP_READ_BIT, - actx->vbo[i]); + actx->vbo[i], + MAP_INTERNAL); if (actx->nr_vbos) actx->mapped_vbos = GL_TRUE; @@ -1655,7 +1657,7 @@ _ae_unmap_vbos(struct gl_context *ctx) assert (!actx->NewState); for (i = 0; i < actx->nr_vbos; i++) - ctx->Driver.UnmapBuffer(ctx, actx->vbo[i]); + ctx->Driver.UnmapBuffer(ctx, actx->vbo[i], MAP_INTERNAL); actx->mapped_vbos = GL_FALSE; } @@ -1701,7 +1703,8 @@ _ae_ArrayElement(GLint elt) /* emit generic attribute elements */ for (at = actx->attribs; at->func; at++) { const GLubyte *src - = ADD_POINTERS(at->array->BufferObj->Pointer, at->array->Ptr) + = ADD_POINTERS(at->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, + at->array->Ptr) + elt * at->array->StrideB; at->func(at->index, src); } @@ -1709,7 +1712,8 @@ _ae_ArrayElement(GLint elt) /* emit conventional arrays elements */ for (aa = actx->arrays; aa->offset != -1 ; aa++) { const GLubyte *src - = ADD_POINTERS(aa->array->BufferObj->Pointer, aa->array->Ptr) + = ADD_POINTERS(aa->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, + aa->array->Ptr) + elt * aa->array->StrideB; CALL_by_offset(disp, (array_func), aa->offset, ((const void *) src)); } diff --git a/mesalib/src/mesa/main/api_loopback.c b/mesalib/src/mesa/main/api_loopback.c index 8a04174c7..d10ae15ea 100644 --- a/mesalib/src/mesa/main/api_loopback.c +++ b/mesalib/src/mesa/main/api_loopback.c @@ -34,7 +34,6 @@ #include "api_loopback.h" #include "mtypes.h" #include "glapi/glapi.h" -#include "glapi/glthread.h" #include "main/dispatch.h" #include "main/context.h" diff --git a/mesalib/src/mesa/main/api_loopback.h b/mesalib/src/mesa/main/api_loopback.h index 0b014ad5a..2195e01e3 100644 --- a/mesalib/src/mesa/main/api_loopback.h +++ b/mesalib/src/mesa/main/api_loopback.h @@ -32,7 +32,6 @@ #include "main/macros.h" // ? #include "main/mtypes.h" // ? #include "glapi/glapi.h" // ? -#include "glapi/glthread.h" // ? #include "main/dispatch.h" // ? #include "main/context.h" // ? diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index af469e046..f3fd1a475 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -69,7 +69,8 @@ _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type, if (_mesa_is_bufferobj(elementBuf)) { /* elements are in a user-defined buffer object. need to map it */ map = ctx->Driver.MapBufferRange(ctx, 0, elementBuf->Size, - GL_MAP_READ_BIT, elementBuf); + GL_MAP_READ_BIT, elementBuf, + MAP_INTERNAL); /* Actual address is the sum of pointers */ indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices); } @@ -92,7 +93,7 @@ _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type, } if (map) { - ctx->Driver.UnmapBuffer(ctx, elementBuf); + ctx->Driver.UnmapBuffer(ctx, elementBuf, MAP_INTERNAL); } return max; @@ -865,7 +866,7 @@ valid_draw_indirect(struct gl_context *ctx, return GL_FALSE; } - if (_mesa_bufferobj_mapped(ctx->DrawIndirectBuffer)) { + if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(DRAW_INDIRECT_BUFFER is mapped)", name); return GL_FALSE; diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index b33ba8016..efb993012 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -119,7 +119,7 @@ _mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj) { unbind_array_object_vbos(ctx, obj); _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL); - _glthread_DESTROY_MUTEX(obj->Mutex); + mtx_destroy(&obj->Mutex); free(obj->Label); free(obj); } @@ -142,7 +142,7 @@ _mesa_reference_vao_(struct gl_context *ctx, GLboolean deleteFlag = GL_FALSE; struct gl_vertex_array_object *oldObj = *ptr; - _glthread_LOCK_MUTEX(oldObj->Mutex); + mtx_lock(&oldObj->Mutex); ASSERT(oldObj->RefCount > 0); oldObj->RefCount--; #if 0 @@ -150,7 +150,7 @@ _mesa_reference_vao_(struct gl_context *ctx, (void *) oldObj, oldObj->Name, oldObj->RefCount); #endif deleteFlag = (oldObj->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldObj->Mutex); + mtx_unlock(&oldObj->Mutex); if (deleteFlag) { ASSERT(ctx->Driver.DeleteArrayObject); @@ -163,7 +163,7 @@ _mesa_reference_vao_(struct gl_context *ctx, if (vao) { /* reference new array object */ - _glthread_LOCK_MUTEX(vao->Mutex); + mtx_lock(&vao->Mutex); if (vao->RefCount == 0) { /* this array's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -178,7 +178,7 @@ _mesa_reference_vao_(struct gl_context *ctx, #endif *ptr = vao; } - _glthread_UNLOCK_MUTEX(vao->Mutex); + mtx_unlock(&vao->Mutex); } } @@ -226,7 +226,7 @@ _mesa_initialize_vao(struct gl_context *ctx, obj->Name = name; - _glthread_INIT_MUTEX(obj->Mutex); + mtx_init(&obj->Mutex, mtx_plain); obj->RefCount = 1; /* Init the individual arrays */ diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index 004528044..5a626f2f4 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -1457,6 +1457,7 @@ copy_array_object(struct gl_context *ctx, /* _Enabled must be the same than on push */ dest->_Enabled = src->_Enabled; + dest->NewArrays = src->NewArrays; dest->_MaxElement = src->_MaxElement; } diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index ca55ef969..2e9e05918 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -207,11 +207,12 @@ static bool bufferobj_range_mapped(const struct gl_buffer_object *obj, GLintptr offset, GLsizeiptr size) { - if (_mesa_bufferobj_mapped(obj)) { + if (_mesa_bufferobj_mapped(obj, MAP_USER)) { const GLintptr end = offset + size; - const GLintptr mapEnd = obj->Offset + obj->Length; + const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset + + obj->Mappings[MAP_USER].Length; - if (!(end <= obj->Offset || offset >= mapEnd)) { + if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) { return true; } } @@ -269,6 +270,9 @@ buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, return NULL; } + if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) + return bufObj; + if (mappedRange) { if (bufferobj_range_mapped(bufObj, offset, size)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); @@ -276,7 +280,7 @@ buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, } } else { - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); return NULL; } @@ -413,7 +417,7 @@ _mesa_delete_buffer_object(struct gl_context *ctx, bufObj->RefCount = -1000; bufObj->Name = ~0; - _glthread_DESTROY_MUTEX(bufObj->Mutex); + mtx_destroy(&bufObj->Mutex); free(bufObj->Label); free(bufObj); } @@ -435,7 +439,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, GLboolean deleteFlag = GL_FALSE; struct gl_buffer_object *oldObj = *ptr; - _glthread_LOCK_MUTEX(oldObj->Mutex); + mtx_lock(&oldObj->Mutex); ASSERT(oldObj->RefCount > 0); oldObj->RefCount--; #if 0 @@ -443,7 +447,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, (void *) oldObj, oldObj->Name, oldObj->RefCount); #endif deleteFlag = (oldObj->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldObj->Mutex); + mtx_unlock(&oldObj->Mutex); if (deleteFlag) { @@ -465,7 +469,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, if (bufObj) { /* reference new buffer */ - _glthread_LOCK_MUTEX(bufObj->Mutex); + mtx_lock(&bufObj->Mutex); if (bufObj->RefCount == 0) { /* this buffer's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -480,7 +484,7 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, #endif *ptr = bufObj; } - _glthread_UNLOCK_MUTEX(bufObj->Mutex); + mtx_unlock(&bufObj->Mutex); } } @@ -496,11 +500,10 @@ _mesa_initialize_buffer_object( struct gl_context *ctx, (void) target; memset(obj, 0, sizeof(struct gl_buffer_object)); - _glthread_INIT_MUTEX(obj->Mutex); + mtx_init(&obj->Mutex, mtx_plain); obj->RefCount = 1; obj->Name = name; obj->Usage = GL_STATIC_DRAW_ARB; - obj->AccessFlags = 0; } @@ -555,21 +558,21 @@ _mesa_total_buffer_object_memory(struct gl_context *ctx) */ static GLboolean _mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size, - const GLvoid * data, GLenum usage, + const GLvoid * data, GLenum usage, GLenum storageFlags, struct gl_buffer_object * bufObj ) { void * new_data; (void) target; - if (bufObj->Data) - _mesa_align_free( bufObj->Data ); + _mesa_align_free( bufObj->Data ); new_data = _mesa_align_malloc( size, ctx->Const.MinMapBufferAlignment ); if (new_data) { bufObj->Data = (GLubyte *) new_data; bufObj->Size = size; bufObj->Usage = usage; + bufObj->StorageFlags = storageFlags; if (data) { memcpy( bufObj->Data, data, size ); @@ -672,33 +675,11 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, GLsizeiptr i; GLubyte *dest; - if (_mesa_bufferobj_mapped(bufObj)) { - GLubyte *data = malloc(size); - GLubyte *dataStart = data; - if (data == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); - return; - } - - if (clearValue == NULL) { - /* Clear with zeros, per the spec */ - memset(data, 0, size); - } - else { - for (i = 0; i < size/clearValueSize; ++i) { - memcpy(data, clearValue, clearValueSize); - data += clearValueSize; - } - } - ctx->Driver.BufferSubData(ctx, offset, size, dataStart, bufObj); - return; - } - ASSERT(ctx->Driver.MapBufferRange); dest = ctx->Driver.MapBufferRange(ctx, offset, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, - bufObj); + bufObj, MAP_INTERNAL); if (!dest) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); @@ -708,7 +689,7 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, if (clearValue == NULL) { /* Clear with zeros, per the spec */ memset(dest, 0, size); - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); return; } @@ -717,7 +698,7 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, dest += clearValueSize; } - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); } @@ -728,16 +709,17 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, static void * _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *bufObj ) + struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; - assert(!_mesa_bufferobj_mapped(bufObj)); + assert(!_mesa_bufferobj_mapped(bufObj, index)); /* Just return a direct pointer to the data */ - bufObj->Pointer = bufObj->Data + offset; - bufObj->Length = length; - bufObj->Offset = offset; - bufObj->AccessFlags = access; - return bufObj->Pointer; + bufObj->Mappings[index].Pointer = bufObj->Data + offset; + bufObj->Mappings[index].Length = length; + bufObj->Mappings[index].Offset = offset; + bufObj->Mappings[index].AccessFlags = access; + return bufObj->Mappings[index].Pointer; } @@ -748,7 +730,8 @@ _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, static void _mesa_buffer_flush_mapped_range( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj ) + struct gl_buffer_object *obj, + gl_map_buffer_index index) { (void) ctx; (void) offset; @@ -766,14 +749,15 @@ _mesa_buffer_flush_mapped_range( struct gl_context *ctx, * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer */ static GLboolean -_mesa_buffer_unmap( struct gl_context *ctx, struct gl_buffer_object *bufObj ) +_mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; /* XXX we might assert here that bufObj->Pointer is non-null */ - bufObj->Pointer = NULL; - bufObj->Length = 0; - bufObj->Offset = 0; - bufObj->AccessFlags = 0x0; + bufObj->Mappings[index].Pointer = NULL; + bufObj->Mappings[index].Length = 0; + bufObj->Mappings[index].Offset = 0; + bufObj->Mappings[index].AccessFlags = 0x0; return GL_TRUE; } @@ -791,14 +775,11 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, { GLubyte *srcPtr, *dstPtr; - /* the buffers should not be mapped */ - assert(!_mesa_bufferobj_mapped(src)); - assert(!_mesa_bufferobj_mapped(dst)); - if (src == dst) { srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size, GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT, src); + GL_MAP_WRITE_BIT, src, + MAP_INTERNAL); if (!srcPtr) return; @@ -807,10 +788,12 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, dstPtr += writeOffset; } else { srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size, - GL_MAP_READ_BIT, src); + GL_MAP_READ_BIT, src, + MAP_INTERNAL); dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size, (GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT), dst); + GL_MAP_INVALIDATE_RANGE_BIT), dst, + MAP_INTERNAL); } /* Note: the src and dst regions will never overlap. Trying to do so @@ -819,9 +802,9 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, if (srcPtr && dstPtr) memcpy(dstPtr, srcPtr, size); - ctx->Driver.UnmapBuffer(ctx, src); + ctx->Driver.UnmapBuffer(ctx, src, MAP_INTERNAL); if (dst != src) - ctx->Driver.UnmapBuffer(ctx, dst); + ctx->Driver.UnmapBuffer(ctx, dst, MAP_INTERNAL); } @@ -835,7 +818,7 @@ _mesa_init_buffer_objects( struct gl_context *ctx ) GLuint i; memset(&DummyBufferObject, 0, sizeof(DummyBufferObject)); - _glthread_INIT_MUTEX(DummyBufferObject.Mutex); + mtx_init(&DummyBufferObject.Mutex, mtx_plain); DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */ _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, @@ -955,10 +938,6 @@ bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) /* bind new buffer */ _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); - - /* Pass BindBuffer call to device driver */ - if (ctx->Driver.BindBuffer) - ctx->Driver.BindBuffer( ctx, target, newBufObj ); } @@ -1023,7 +1002,6 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver) /* GL_ARB_vertex/pixel_buffer_object */ driver->NewBufferObject = _mesa_new_buffer_object; driver->DeleteBuffer = _mesa_delete_buffer_object; - driver->BindBuffer = NULL; driver->BufferData = _mesa_buffer_data; driver->BufferSubData = _mesa_buffer_subdata; driver->GetBufferSubData = _mesa_buffer_get_subdata; @@ -1041,6 +1019,21 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver) } +void +_mesa_buffer_unmap_all_mappings(struct gl_context *ctx, + struct gl_buffer_object *bufObj) +{ + int i; + + for (i = 0; i < MAP_COUNT; i++) { + if (_mesa_bufferobj_mapped(bufObj, i)) { + ctx->Driver.UnmapBuffer(ctx, bufObj, i); + ASSERT(bufObj->Mappings[i].Pointer == NULL); + bufObj->Mappings[i].AccessFlags = 0; + } + } +} + /**********************************************************************/ /* API Functions */ @@ -1077,7 +1070,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) return; } - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); for (i = 0; i < n; i++) { struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); @@ -1087,12 +1080,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject); - if (_mesa_bufferobj_mapped(bufObj)) { - /* if mapped, unmap it now */ - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = 0; - bufObj->Pointer = NULL; - } + _mesa_buffer_unmap_all_mappings(ctx, bufObj); /* unbind any vertex pointers bound to this buffer */ for (j = 0; j < Elements(vao->VertexBinding); j++) { @@ -1169,7 +1157,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) } } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -1201,7 +1189,7 @@ _mesa_GenBuffers(GLsizei n, GLuint *buffer) /* * This must be atomic (generation and allocation of buffer object IDs) */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); @@ -1212,7 +1200,7 @@ _mesa_GenBuffers(GLsizei n, GLuint *buffer) buffer[i] = first + i; } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -1230,14 +1218,72 @@ _mesa_IsBuffer(GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); bufObj = _mesa_lookup_bufferobj(ctx, id); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); return bufObj && bufObj != &DummyBufferObject; } +void GLAPIENTRY +_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + if (size <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(size <= 0)"); + return; + } + + if (flags & ~(GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT | + GL_DYNAMIC_STORAGE_BIT | + GL_CLIENT_STORAGE_BIT)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags)"); + return; + } + + if (flags & GL_MAP_PERSISTENT_BIT && + !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=READ/WRITE)"); + return; + } + + if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=PERSISTENT)"); + return; + } + + bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION); + if (!bufObj) + return; + + if (bufObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage(immutable)"); + return; + } + + /* Unmap the existing buffer. We'll replace it now. Not an error. */ + _mesa_buffer_unmap_all_mappings(ctx, bufObj); + + FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); + + bufObj->Written = GL_TRUE; + bufObj->Immutable = GL_TRUE; + + ASSERT(ctx->Driver.BufferData); + if (!ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW, + flags, bufObj)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()"); + } +} + + void GLAPIENTRY _mesa_BufferData(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage) @@ -1290,12 +1336,13 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, if (!bufObj) return; - if (_mesa_bufferobj_mapped(bufObj)) { - /* Unmap the existing buffer. We'll replace it now. Not an error. */ - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = 0; - ASSERT(bufObj->Pointer == NULL); - } + if (bufObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData(immutable)"); + return; + } + + /* Unmap the existing buffer. We'll replace it now. Not an error. */ + _mesa_buffer_unmap_all_mappings(ctx, bufObj); FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); @@ -1311,7 +1358,11 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, #endif ASSERT(ctx->Driver.BufferData); - if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) { + if (!ctx->Driver.BufferData(ctx, target, size, data, usage, + GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT, + bufObj)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()"); } } @@ -1332,6 +1383,12 @@ _mesa_BufferSubData(GLenum target, GLintptrARB offset, return; } + if (bufObj->Immutable && + !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubData"); + return; + } + if (size == 0) return; @@ -1377,7 +1434,7 @@ _mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format, return; } - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_check_disallowed_mapping(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glClearBufferData(buffer currently mapped)"); return; @@ -1451,8 +1508,10 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, if (data == NULL) { /* clear to zeros, per the spec */ - ctx->Driver.ClearBufferSubData(ctx, offset, size, - NULL, 0, bufObj); + if (size > 0) { + ctx->Driver.ClearBufferSubData(ctx, offset, size, + NULL, 0, bufObj); + } return; } @@ -1462,8 +1521,10 @@ _mesa_ClearBufferSubData(GLenum target, GLenum internalformat, return; } - ctx->Driver.ClearBufferSubData(ctx, offset, size, - clearValue, clearValueSize, bufObj); + if (size > 0) { + ctx->Driver.ClearBufferSubData(ctx, offset, size, + clearValue, clearValueSize, bufObj); + } } @@ -1505,7 +1566,21 @@ _mesa_MapBuffer(GLenum target, GLenum access) if (!bufObj) return NULL; - if (_mesa_bufferobj_mapped(bufObj)) { + if (accessFlags & GL_MAP_READ_BIT && + !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBuffer(invalid read flag)"); + return NULL; + } + + if (accessFlags & GL_MAP_WRITE_BIT && + !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBuffer(invalid write flag)"); + return NULL; + } + + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); return NULL; } @@ -1517,7 +1592,8 @@ _mesa_MapBuffer(GLenum target, GLenum access) } ASSERT(ctx->Driver.MapBufferRange); - map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj); + map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj, + MAP_USER); if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); return NULL; @@ -1527,10 +1603,10 @@ _mesa_MapBuffer(GLenum target, GLenum access) * This is important because other modules (like VBO) might call * the driver function directly. */ - ASSERT(bufObj->Pointer == map); - ASSERT(bufObj->Length == bufObj->Size); - ASSERT(bufObj->Offset == 0); - bufObj->AccessFlags = accessFlags; + ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); + ASSERT(bufObj->Mappings[MAP_USER].Length == bufObj->Size); + ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); + bufObj->Mappings[MAP_USER].AccessFlags = accessFlags; } if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) @@ -1558,7 +1634,7 @@ _mesa_MapBuffer(GLenum target, GLenum access) } #endif - return bufObj->Pointer; + return bufObj->Mappings[MAP_USER].Pointer; } @@ -1574,7 +1650,7 @@ _mesa_UnmapBuffer(GLenum target) if (!bufObj) return GL_FALSE; - if (!_mesa_bufferobj_mapped(bufObj)) { + if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); return GL_FALSE; } @@ -1615,11 +1691,11 @@ _mesa_UnmapBuffer(GLenum target) } #endif - status = ctx->Driver.UnmapBuffer( ctx, bufObj ); - bufObj->AccessFlags = 0; - ASSERT(bufObj->Pointer == NULL); - ASSERT(bufObj->Offset == 0); - ASSERT(bufObj->Length == 0); + status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER); + bufObj->Mappings[MAP_USER].AccessFlags = 0; + ASSERT(bufObj->Mappings[MAP_USER].Pointer == NULL); + ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); + ASSERT(bufObj->Mappings[MAP_USER].Length == 0); return status; } @@ -1644,25 +1720,36 @@ _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(ctx, bufObj->AccessFlags); + *params = simplified_access_mode(ctx, + bufObj->Mappings[MAP_USER].AccessFlags); return; case GL_BUFFER_MAPPED_ARB: - *params = _mesa_bufferobj_mapped(bufObj); + *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); return; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->AccessFlags; + *params = bufObj->Mappings[MAP_USER].AccessFlags; return; case GL_BUFFER_MAP_OFFSET: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Offset; + *params = (GLint) bufObj->Mappings[MAP_USER].Offset; return; case GL_BUFFER_MAP_LENGTH: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Length; + *params = (GLint) bufObj->Mappings[MAP_USER].Length; + return; + case GL_BUFFER_IMMUTABLE_STORAGE: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->Immutable; + return; + case GL_BUFFER_STORAGE_FLAGS: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->StorageFlags; return; default: ; /* fall-through */ @@ -1698,25 +1785,36 @@ _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(ctx, bufObj->AccessFlags); + *params = simplified_access_mode(ctx, + bufObj->Mappings[MAP_USER].AccessFlags); return; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->AccessFlags; + *params = bufObj->Mappings[MAP_USER].AccessFlags; return; case GL_BUFFER_MAPPED_ARB: - *params = _mesa_bufferobj_mapped(bufObj); + *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); return; case GL_BUFFER_MAP_OFFSET: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->Offset; + *params = bufObj->Mappings[MAP_USER].Offset; return; case GL_BUFFER_MAP_LENGTH: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->Length; + *params = bufObj->Mappings[MAP_USER].Length; + return; + case GL_BUFFER_IMMUTABLE_STORAGE: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->Immutable; + return; + case GL_BUFFER_STORAGE_FLAGS: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->StorageFlags; return; default: ; /* fall-through */ @@ -1744,7 +1842,7 @@ _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) if (!bufObj) return; - *params = bufObj->Pointer; + *params = bufObj->Mappings[MAP_USER].Pointer; } @@ -1766,13 +1864,13 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, if (!dst) return; - if (_mesa_bufferobj_mapped(src)) { + if (_mesa_check_disallowed_mapping(src)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyBufferSubData(readBuffer is mapped)"); return; } - if (_mesa_bufferobj_mapped(dst)) { + if (_mesa_check_disallowed_mapping(dst)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyBufferSubData(writeBuffer is mapped)"); return; @@ -1839,6 +1937,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; void *map; + GLbitfield allowed_access; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); @@ -1873,13 +1972,20 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, return NULL; } - if (access & ~(GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_UNSYNCHRONIZED_BIT)) { - /* generate an error if any undefind bit is set */ + allowed_access = GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if (ctx->Extensions.ARB_buffer_storage) { + allowed_access |= GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT; + } + + if (access & ~allowed_access) { + /* generate an error if any other than allowed bit is set */ _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(access)"); return NULL; } @@ -1910,13 +2016,41 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, if (!bufObj) return NULL; + if (access & GL_MAP_READ_BIT && + !(bufObj->StorageFlags & GL_MAP_READ_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid read flag)"); + return NULL; + } + + if (access & GL_MAP_WRITE_BIT && + !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid write flag)"); + return NULL; + } + + if (access & GL_MAP_COHERENT_BIT && + !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid coherent flag)"); + return NULL; + } + + if (access & GL_MAP_PERSISTENT_BIT && + !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMapBufferRange(invalid persistent flag)"); + return NULL; + } + if (offset + length > bufObj->Size) { _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(offset + length > size)"); return NULL; } - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferRange(buffer already mapped)"); return NULL; @@ -1931,15 +2065,16 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, /* Mapping zero bytes should return a non-null pointer. */ if (!length) { static long dummy = 0; - bufObj->Pointer = &dummy; - bufObj->Length = length; - bufObj->Offset = offset; - bufObj->AccessFlags = access; - return bufObj->Pointer; + bufObj->Mappings[MAP_USER].Pointer = &dummy; + bufObj->Mappings[MAP_USER].Length = length; + bufObj->Mappings[MAP_USER].Offset = offset; + bufObj->Mappings[MAP_USER].AccessFlags = access; + return bufObj->Mappings[MAP_USER].Pointer; } ASSERT(ctx->Driver.MapBufferRange); - map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj); + map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj, + MAP_USER); if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); } @@ -1948,10 +2083,10 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, * This is important because other modules (like VBO) might call * the driver function directly. */ - ASSERT(bufObj->Pointer == map); - ASSERT(bufObj->Length == length); - ASSERT(bufObj->Offset == offset); - ASSERT(bufObj->AccessFlags == access); + ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); + ASSERT(bufObj->Mappings[MAP_USER].Length == length); + ASSERT(bufObj->Mappings[MAP_USER].Offset == offset); + ASSERT(bufObj->Mappings[MAP_USER].AccessFlags == access); } return map; @@ -1990,30 +2125,33 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) if (!bufObj) return; - if (!_mesa_bufferobj_mapped(bufObj)) { + if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { /* buffer is not mapped */ _mesa_error(ctx, GL_INVALID_OPERATION, "glFlushMappedBufferRange(buffer is not mapped)"); return; } - if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { + if ((bufObj->Mappings[MAP_USER].AccessFlags & + GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)"); return; } - if (offset + length > bufObj->Length) { + if (offset + length > bufObj->Mappings[MAP_USER].Length) { _mesa_error(ctx, GL_INVALID_VALUE, "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)", - (long)offset, (long)length, (long)bufObj->Length); + (long)offset, (long)length, + (long)bufObj->Mappings[MAP_USER].Length); return; } - ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT); + ASSERT(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT); if (ctx->Driver.FlushMappedBufferRange) - ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj); + ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj, + MAP_USER); } @@ -2660,13 +2798,15 @@ _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset, return; } - /* The GL_ARB_invalidate_subdata spec says: + /* The OpenGL 4.4 (Core Profile) spec says: * - * "An INVALID_OPERATION error is generated if the buffer is currently - * mapped by MapBuffer, or if the invalidate range intersects the range - * currently mapped by MapBufferRange." + * "An INVALID_OPERATION error is generated if buffer is currently + * mapped by MapBuffer or if the invalidate range intersects the range + * currently mapped by MapBufferRange, unless it was mapped + * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." */ - if (bufferobj_range_mapped(bufObj, offset, length)) { + if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) && + bufferobj_range_mapped(bufObj, offset, length)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glInvalidateBufferSubData(intersection with mapped " "range)"); @@ -2693,13 +2833,14 @@ _mesa_InvalidateBufferData(GLuint buffer) return; } - /* The GL_ARB_invalidate_subdata spec says: + /* The OpenGL 4.4 (Core Profile) spec says: * - * "An INVALID_OPERATION error is generated if the buffer is currently - * mapped by MapBuffer, or if the invalidate range intersects the range - * currently mapped by MapBufferRange." + * "An INVALID_OPERATION error is generated if buffer is currently + * mapped by MapBuffer or if the invalidate range intersects the range + * currently mapped by MapBufferRange, unless it was mapped + * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." */ - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_check_disallowed_mapping(bufObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glInvalidateBufferData(intersection with mapped " "range)"); diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h index 71988b0d9..9814552eb 100644 --- a/mesalib/src/mesa/main/bufferobj.h +++ b/mesalib/src/mesa/main/bufferobj.h @@ -37,11 +37,21 @@ */ -/** Is the given buffer object currently mapped? */ +/** Is the given buffer object currently mapped by the GL user? */ static inline GLboolean -_mesa_bufferobj_mapped(const struct gl_buffer_object *obj) +_mesa_bufferobj_mapped(const struct gl_buffer_object *obj, + gl_map_buffer_index index) { - return obj->Pointer != NULL; + return obj->Mappings[index].Pointer != NULL; +} + +/** Can we not use this buffer while mapped? */ +static inline GLboolean +_mesa_check_disallowed_mapping(const struct gl_buffer_object *obj) +{ + return _mesa_bufferobj_mapped(obj, MAP_USER) && + !(obj->Mappings[MAP_USER].AccessFlags & + GL_MAP_PERSISTENT_BIT); } /** @@ -101,6 +111,9 @@ _mesa_total_buffer_object_memory(struct gl_context *ctx); extern void _mesa_init_buffer_object_functions(struct dd_function_table *driver); +extern void +_mesa_buffer_unmap_all_mappings(struct gl_context *ctx, + struct gl_buffer_object *bufObj); /* * API functions @@ -117,6 +130,10 @@ _mesa_GenBuffers(GLsizei n, GLuint * buffer); GLboolean GLAPIENTRY _mesa_IsBuffer(GLuint buffer); +void GLAPIENTRY +_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags); + void GLAPIENTRY _mesa_BufferData(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 458d8e59b..5b77ce103 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -106,6 +106,7 @@ #include "matrix.h" #include "multisample.h" #include "performance_monitor.h" +#include "pipelineobj.h" #include "pixel.h" #include "pixelstore.h" #include "points.h" @@ -363,7 +364,7 @@ dummy_enum_func(void) * * \sa Used by one_time_init(). */ -_glthread_DECLARE_STATIC_MUTEX(OneTimeLock); +mtx_t OneTimeLock = _MTX_INITIALIZER_NP; @@ -381,7 +382,7 @@ one_time_init( struct gl_context *ctx ) { static GLbitfield api_init_mask = 0x0; - _glthread_LOCK_MUTEX(OneTimeLock); + mtx_lock(&OneTimeLock); /* truly one-time init */ if (!api_init_mask) { @@ -422,7 +423,7 @@ one_time_init( struct gl_context *ctx ) api_init_mask |= 1 << ctx->API; - _glthread_UNLOCK_MUTEX(OneTimeLock); + mtx_unlock(&OneTimeLock); /* Hopefully atexit() is widely available. If not, we may need some * #ifdef tests here. @@ -603,9 +604,6 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.ViewportBounds.Min = 0; ctx->Const.ViewportBounds.Max = 0; - /* Driver must override if it supports ARB_viewport_array */ - ctx->Const.MaxViewports = 1; - /** GL_ARB_uniform_buffer_object */ ctx->Const.MaxCombinedUniformBlocks = 36; ctx->Const.MaxUniformBufferBindings = 36; @@ -814,6 +812,7 @@ init_attrib_groups(struct gl_context *ctx) _mesa_init_matrix( ctx ); _mesa_init_multisample( ctx ); _mesa_init_performance_monitors( ctx ); + _mesa_init_pipeline( ctx ); _mesa_init_pixel( ctx ); _mesa_init_pixelstore( ctx ); _mesa_init_point( ctx ); @@ -1219,6 +1218,7 @@ _mesa_free_context_data( struct gl_context *ctx ) _mesa_free_texture_data( ctx ); _mesa_free_matrix_data( ctx ); _mesa_free_viewport_data( ctx ); + _mesa_free_pipeline_data(ctx); _mesa_free_program_data(ctx); _mesa_free_shader_state(ctx); _mesa_free_queryobj_data(ctx); @@ -1769,93 +1769,59 @@ _mesa_check_blend_func_error(struct gl_context *ctx) return GL_TRUE; } -/** - * Prior to drawing anything with glBegin, glDrawArrays, etc. this function - * is called to see if it's valid to render. This involves checking that - * the current shader is valid and the framebuffer is complete. - * If an error is detected it'll be recorded here. - * \return GL_TRUE if OK to render, GL_FALSE if not - */ -GLboolean -_mesa_valid_to_render(struct gl_context *ctx, const char *where) +static bool +shader_linked_or_absent(struct gl_context *ctx, + const struct gl_shader_program *shProg, + bool *shader_present, const char *where) { - bool vert_from_glsl_shader = false; - bool geom_from_glsl_shader = false; - bool frag_from_glsl_shader = false; - - /* This depends on having up to date derived state (shaders) */ - if (ctx->NewState) - _mesa_update_state(ctx); + if (shProg) { + *shader_present = true; - if (ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]) { - vert_from_glsl_shader = true; - - if (!ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(shader not linked)", where); - return GL_FALSE; + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(shader not linked)", where); + return false; } #if 0 /* not normally enabled */ { char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, - ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX], - errMsg)) { + if (!_mesa_validate_shader_program(ctx, shProg, errMsg)) { _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_VERTEX]->Name, errMsg); + shProg->Name, errMsg); } } #endif } - if (ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]) { - geom_from_glsl_shader = true; + return true; +} - if (!ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(shader not linked)", where); - return GL_FALSE; - } -#if 0 /* not normally enabled */ - { - char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, - ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY], - errMsg)) { - _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_GEOMETRY]->Name, - errMsg); - } - } -#endif - } +/** + * Prior to drawing anything with glBegin, glDrawArrays, etc. this function + * is called to see if it's valid to render. This involves checking that + * the current shader is valid and the framebuffer is complete. + * If an error is detected it'll be recorded here. + * \return GL_TRUE if OK to render, GL_FALSE if not + */ +GLboolean +_mesa_valid_to_render(struct gl_context *ctx, const char *where) +{ + bool from_glsl_shader[MESA_SHADER_COMPUTE] = { false }; + unsigned i; - if (ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]) { - frag_from_glsl_shader = true; + /* This depends on having up to date derived state (shaders) */ + if (ctx->NewState) + _mesa_update_state(ctx); - if (!ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]->LinkStatus) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(shader not linked)", where); + for (i = 0; i < MESA_SHADER_COMPUTE; i++) { + if (!shader_linked_or_absent(ctx, ctx->Shader.CurrentProgram[i], + &from_glsl_shader[i], where)) return GL_FALSE; - } -#if 0 /* not normally enabled */ - { - char errMsg[100]; - if (!_mesa_validate_shader_program(ctx, - ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT], - errMsg)) { - _mesa_warning(ctx, "Shader program %u is invalid: %s", - ctx->Shader.CurrentProgram[MESA_SHADER_FRAGMENT]->Name, - errMsg); - } - } -#endif } /* Any shader stages that are not supplied by the GLSL shader and have * assembly shaders enabled must now be validated. */ - if (!vert_from_glsl_shader + if (!from_glsl_shader[MESA_SHADER_VERTEX] && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(vertex program not valid)", where); @@ -1865,9 +1831,9 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where) /* FINISHME: If GL_NV_geometry_program4 is ever supported, the current * FINISHME: geometry program should validated here. */ - (void) geom_from_glsl_shader; + (void) from_glsl_shader[MESA_SHADER_GEOMETRY]; - if (!frag_from_glsl_shader) { + if (!from_glsl_shader[MESA_SHADER_FRAGMENT]) { if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(fragment program not valid)", where); diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index ac317e399..971524135 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -399,6 +399,13 @@ struct dd_function_table { void (*UnmapRenderbuffer)(struct gl_context *ctx, struct gl_renderbuffer *rb); + /** + * Optional driver entrypoint that binds a non-texture renderbuffer's + * contents to a texture image. + */ + GLboolean (*BindRenderbufferTexImage)(struct gl_context *ctx, + struct gl_renderbuffer *rb, + struct gl_texture_image *texImage); /*@}*/ @@ -564,9 +571,6 @@ struct dd_function_table { * \name Vertex/pixel buffer object functions */ /*@{*/ - void (*BindBuffer)( struct gl_context *ctx, GLenum target, - struct gl_buffer_object *obj ); - struct gl_buffer_object * (*NewBufferObject)(struct gl_context *ctx, GLuint buffer, GLenum target); @@ -574,7 +578,7 @@ struct dd_function_table { GLboolean (*BufferData)(struct gl_context *ctx, GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage, - struct gl_buffer_object *obj); + GLenum storageFlags, struct gl_buffer_object *obj); void (*BufferSubData)( struct gl_context *ctx, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data, @@ -601,14 +605,17 @@ struct dd_function_table { */ void * (*MapBufferRange)( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *obj); + struct gl_buffer_object *obj, + gl_map_buffer_index index); void (*FlushMappedBufferRange)(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj); + struct gl_buffer_object *obj, + gl_map_buffer_index index); GLboolean (*UnmapBuffer)( struct gl_context *ctx, - struct gl_buffer_object *obj ); + struct gl_buffer_object *obj, + gl_map_buffer_index index); /*@}*/ /** diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c index 08943c9f9..d431fd221 100644 --- a/mesalib/src/mesa/main/dlist.c +++ b/mesalib/src/mesa/main/dlist.c @@ -914,7 +914,8 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, map = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, - GL_MAP_READ_BIT, unpack->BufferObj); + GL_MAP_READ_BIT, unpack->BufferObj, + MAP_INTERNAL); if (!map) { /* unable to map src buffer! */ _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO"); @@ -928,7 +929,7 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, image = _mesa_unpack_image(dimensions, width, height, depth, format, type, src, unpack); - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); if (!image) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction"); @@ -8176,7 +8177,7 @@ _mesa_GenLists(GLsizei range) /* * Make this an atomic operation */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); base = _mesa_HashFindFreeKeyBlock(ctx->Shared->DisplayList, range); if (base) { @@ -8188,7 +8189,7 @@ _mesa_GenLists(GLsizei range) } } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); return base; } diff --git a/mesalib/src/mesa/main/drawpix.c b/mesalib/src/mesa/main/drawpix.c index 096615c05..63e5870e6 100644 --- a/mesalib/src/mesa/main/drawpix.c +++ b/mesalib/src/mesa/main/drawpix.c @@ -151,7 +151,7 @@ _mesa_DrawPixels( GLsizei width, GLsizei height, "glDrawPixels(invalid PBO access)"); goto end; } - if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels(PBO is mapped)"); @@ -335,7 +335,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height, "glBitmap(invalid PBO access)"); return; } - if (_mesa_bufferobj_mapped(ctx->Unpack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Unpack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index 40508a456..edd4751e1 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -32,6 +32,7 @@ #include "clip.h" #include "context.h" #include "enable.h" +#include "errors.h" #include "light.h" #include "simple_list.h" #include "mtypes.h" @@ -367,14 +368,26 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) ctx->Depth.Test = state; break; case GL_DEBUG_OUTPUT: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_enum_error; - ctx->Debug.DebugOutput = state; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->DebugOutput = state; + } + } break; case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_enum_error; - ctx->Debug.SyncOutput = state; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->SyncOutput = state; + } + } break; case GL_DITHER: if (ctx->Color.DitherFlag == state) @@ -1228,11 +1241,19 @@ _mesa_IsEnabled( GLenum cap ) case GL_DEBUG_OUTPUT: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - return ctx->Debug.DebugOutput; + if (ctx->Debug) { + return ctx->Debug->DebugOutput; + } else { + return GL_FALSE; + } case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; - return ctx->Debug.SyncOutput; + if (ctx->Debug) { + return ctx->Debug->SyncOutput; + } else { + return GL_FALSE; + } case GL_DEPTH_TEST: return ctx->Depth.Test; case GL_DITHER: diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c index 28357e0e8..ca73a6686 100644 --- a/mesalib/src/mesa/main/errors.c +++ b/mesalib/src/mesa/main/errors.c @@ -37,12 +37,11 @@ #include "mtypes.h" #include "version.h" #include "hash_table.h" -#include "glapi/glthread.h" #define MESSAGE_LOG 1 #define MESSAGE_LOG_ARB 2 -_glthread_DECLARE_STATIC_MUTEX(DynamicIDMutex); +static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP; static GLuint NextDynamicID = 1; struct gl_debug_severity @@ -81,6 +80,7 @@ static const GLenum debug_severity_enums[] = { GL_DEBUG_SEVERITY_NOTIFICATION, }; + static enum mesa_debug_source gl_enum_to_debug_source(GLenum e) { @@ -117,6 +117,7 @@ gl_enum_to_debug_severity(GLenum e) return i; } + /** * Handles generating a GL_ARB_debug_output message ID generated by the GL or * GLSL compiler. @@ -134,13 +135,14 @@ static void debug_get_id(GLuint *id) { if (!(*id)) { - _glthread_LOCK_MUTEX(DynamicIDMutex); + mtx_lock(&DynamicIDMutex); if (!(*id)) *id = NextDynamicID++; - _glthread_UNLOCK_MUTEX(DynamicIDMutex); + mtx_unlock(&DynamicIDMutex); } } + /* * We store a bitfield in the hash table, with five possible values total. * @@ -182,6 +184,50 @@ enum { ENABLED = ENABLED_BIT | FOUND_BIT }; + +/** + * Return debug state for the context. The debug state will be allocated + * and initialized upon the first call. + */ +struct gl_debug_state * +_mesa_get_debug_state(struct gl_context *ctx) +{ + if (!ctx->Debug) { + ctx->Debug = CALLOC_STRUCT(gl_debug_state); + if (!ctx->Debug) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state"); + } + else { + struct gl_debug_state *debug = ctx->Debug; + int s, t, sev; + + /* Enable all the messages with severity HIGH or MEDIUM by default. */ + memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE, + sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH]); + memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE, + sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]); + memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE, + sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW]); + + /* Initialize state for filtering known debug messages. */ + for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) { + for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { + debug->Namespaces[0][s][t].IDs = _mesa_NewHashTable(); + assert(debug->Namespaces[0][s][t].IDs); + + for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) { + make_empty_list(&debug->Namespaces[0][s][t].Severity[sev]); + } + } + } + } + } + + return ctx->Debug; +} + + + /** * Returns the state of the given message source/type/ID tuple. */ @@ -192,52 +238,64 @@ should_log(struct gl_context *ctx, GLuint id, enum mesa_debug_severity severity) { - GLint gstack = ctx->Debug.GroupStackDepth; - struct gl_debug_namespace *nspace = - &ctx->Debug.Namespaces[gstack][source][type]; - uintptr_t state; + struct gl_debug_state *debug; + uintptr_t state = 0; - if (!ctx->Debug.DebugOutput) + if (!ctx->Debug) { + /* no debug state set so far */ return GL_FALSE; + } - /* In addition to not being able to store zero as a value, HashTable also - can't use zero as a key. */ - if (id) - state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); - else - state = nspace->ZeroID; - - /* Only do this once for each ID. This makes sure the ID exists in, - at most, one list, and does not pointlessly appear multiple times. */ - if (!(state & KNOWN_SEVERITY)) { - struct gl_debug_severity *entry; - - if (state == NOT_FOUND) { - if (ctx->Debug.Defaults[gstack][severity][source][type]) - state = ENABLED; - else - state = DISABLED; - } - - entry = malloc(sizeof *entry); - if (!entry) - goto out; + debug = _mesa_get_debug_state(ctx); + if (debug) { + const GLint gstack = debug->GroupStackDepth; + struct gl_debug_namespace *nspace = + &debug->Namespaces[gstack][source][type]; - state |= KNOWN_SEVERITY; + if (!debug->DebugOutput) + return GL_FALSE; + /* In addition to not being able to store zero as a value, HashTable also + * can't use zero as a key. + */ if (id) - _mesa_HashInsert(nspace->IDs, id, (void*)state); + state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); else - nspace->ZeroID = state; + state = nspace->ZeroID; - entry->ID = id; - insert_at_tail(&nspace->Severity[severity], &entry->link); - } + /* Only do this once for each ID. This makes sure the ID exists in, + * at most, one list, and does not pointlessly appear multiple times. + */ + if (!(state & KNOWN_SEVERITY)) { + struct gl_debug_severity *entry; + + if (state == NOT_FOUND) { + if (debug->Defaults[gstack][severity][source][type]) + state = ENABLED; + else + state = DISABLED; + } + + entry = malloc(sizeof *entry); + if (!entry) + goto out; + + state |= KNOWN_SEVERITY; + if (id) + _mesa_HashInsert(nspace->IDs, id, (void*)state); + else + nspace->ZeroID = state; + + entry->ID = id; + insert_at_tail(&nspace->Severity[severity], &entry->link); + } + } out: return !!(state & ENABLED_BIT); } + /** * Sets the state of the given message source/type/ID tuple. */ @@ -247,33 +305,39 @@ set_message_state(struct gl_context *ctx, enum mesa_debug_type type, GLuint id, GLboolean enabled) { - GLint gstack = ctx->Debug.GroupStackDepth; - struct gl_debug_namespace *nspace = - &ctx->Debug.Namespaces[gstack][source][type]; - uintptr_t state; - - /* In addition to not being able to store zero as a value, HashTable also - can't use zero as a key. */ - if (id) - state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); - else - state = nspace->ZeroID; - - if (state == NOT_FOUND) - state = enabled ? ENABLED : DISABLED; - else { - if (enabled) - state |= ENABLED_BIT; + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + + if (debug) { + GLint gstack = debug->GroupStackDepth; + struct gl_debug_namespace *nspace = + &debug->Namespaces[gstack][source][type]; + uintptr_t state; + + /* In addition to not being able to store zero as a value, HashTable also + * can't use zero as a key. + */ + if (id) + state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id); else - state &= ~ENABLED_BIT; - } + state = nspace->ZeroID; - if (id) - _mesa_HashInsert(nspace->IDs, id, (void*)state); - else - nspace->ZeroID = state; + if (state == NOT_FOUND) + state = enabled ? ENABLED : DISABLED; + else { + if (enabled) + state |= ENABLED_BIT; + else + state &= ~ENABLED_BIT; + } + + if (id) + _mesa_HashInsert(nspace->IDs, id, (void*)state); + else + nspace->ZeroID = state; + } } + static void store_message_details(struct gl_debug_msg *emptySlot, enum mesa_debug_source source, @@ -307,7 +371,8 @@ store_message_details(struct gl_debug_msg *emptySlot, } } - /** + +/** * Remap any type exclusive to KHR_debug to something suitable * for ARB_debug_output */ @@ -326,6 +391,7 @@ remap_type(GLenum type) { return type; } + /** * Remap severity exclusive to KHR_debug to something suitable * for ARB_debug_output @@ -339,6 +405,7 @@ remap_severity(GLenum severity) { return severity; } + /** * 'buf' is not necessarily a null-terminated string. When logging, copy * 'len' characters from it, store them in a new, null-terminated string, @@ -346,49 +413,51 @@ remap_severity(GLenum severity) { * the null terminator this time. */ static void -_mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source, - enum mesa_debug_type type, GLuint id, - enum mesa_debug_severity severity, GLint len, const char *buf) +log_msg(struct gl_context *ctx, enum mesa_debug_source source, + enum mesa_debug_type type, GLuint id, + enum mesa_debug_severity severity, GLint len, const char *buf) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); GLint nextEmpty; struct gl_debug_msg *emptySlot; + if (!debug) + return; + assert(len >= 0 && len < MAX_DEBUG_MESSAGE_LENGTH); if (!should_log(ctx, source, type, id, severity)) return; - if (ctx->Debug.Callback) { + if (debug->Callback) { GLenum gl_type = debug_type_enums[type]; GLenum gl_severity = debug_severity_enums[severity]; - if (ctx->Debug.ARBCallback) { + if (debug->ARBCallback) { gl_severity = remap_severity(gl_severity); gl_type = remap_type(gl_type); } - ctx->Debug.Callback(debug_source_enums[source], - gl_type, - id, - gl_severity, - len, buf, ctx->Debug.CallbackData); + debug->Callback(debug_source_enums[source], gl_type, id, gl_severity, + len, buf, debug->CallbackData); return; } - if (ctx->Debug.NumMessages == MAX_DEBUG_LOGGED_MESSAGES) + if (debug->NumMessages == MAX_DEBUG_LOGGED_MESSAGES) return; - nextEmpty = (ctx->Debug.NextMsg + ctx->Debug.NumMessages) + nextEmpty = (debug->NextMsg + debug->NumMessages) % MAX_DEBUG_LOGGED_MESSAGES; - emptySlot = &ctx->Debug.Log[nextEmpty]; + emptySlot = &debug->Log[nextEmpty]; store_message_details(emptySlot, source, type, id, severity, len, buf); - if (ctx->Debug.NumMessages == 0) - ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length; + if (debug->NumMessages == 0) + debug->NextMsgLength = debug->Log[debug->NextMsg].length; - ctx->Debug.NumMessages++; + debug->NumMessages++; } + /** * Pop the oldest debug message out of the log. * Writes the message string, including the null terminator, into 'buf', @@ -400,20 +469,21 @@ _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source, * indicates failure. */ static GLsizei -_mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, - GLuint *id, GLenum *severity, GLsizei bufSize, char *buf, - unsigned caller) +get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, + GLuint *id, GLenum *severity, GLsizei bufSize, char *buf, + unsigned caller) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); struct gl_debug_msg *msg; GLsizei length; - if (ctx->Debug.NumMessages == 0) + if (!debug || debug->NumMessages == 0) return 0; - msg = &ctx->Debug.Log[ctx->Debug.NextMsg]; + msg = &debug->Log[debug->NextMsg]; length = msg->length; - assert(length > 0 && length == ctx->Debug.NextMsgLength); + assert(length > 0 && length == debug->NextMsgLength); if (bufSize < length && buf != NULL) return 0; @@ -423,15 +493,20 @@ _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, if (caller == MESSAGE_LOG_ARB) *severity = remap_severity(*severity); } - if (source) + + if (source) { *source = debug_source_enums[msg->source]; + } + if (type) { *type = debug_type_enums[msg->type]; if (caller == MESSAGE_LOG_ARB) *type = remap_type(*type); } - if (id) + + if (id) { *id = msg->id; + } if (buf) { assert(msg->message[length-1] == '\0'); @@ -443,14 +518,15 @@ _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, msg->message = NULL; msg->length = 0; - ctx->Debug.NumMessages--; - ctx->Debug.NextMsg++; - ctx->Debug.NextMsg %= MAX_DEBUG_LOGGED_MESSAGES; - ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length; + debug->NumMessages--; + debug->NextMsg++; + debug->NextMsg %= MAX_DEBUG_LOGGED_MESSAGES; + debug->NextMsgLength = debug->Log[debug->NextMsg].length; return length; } + /** * Verify that source, type, and severity are valid enums. * glDebugMessageInsertARB only accepts two values for 'source', @@ -523,14 +599,14 @@ validate_params(struct gl_context *ctx, unsigned caller, return GL_TRUE; error: - { - _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s" - "(source=0x%x, type=0x%x, severity=0x%x)", callerstr, - source, type, severity); - } + _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s" + "(source=0x%x, type=0x%x, severity=0x%x)", callerstr, + source, type, severity); + return GL_FALSE; } + /** * Set the state of all message IDs found in the given intersection of * 'source', 'type', and 'severity'. The _COUNT enum can be used for @@ -549,8 +625,12 @@ control_messages(struct gl_context *ctx, enum mesa_debug_severity severity, GLboolean enabled) { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); int s, t, sev, smax, tmax, sevmax; - GLint gstack = ctx->Debug.GroupStackDepth; + const GLint gstack = debug ? debug->GroupStackDepth : 0; + + if (!debug) + return; if (source == MESA_DEBUG_SOURCE_COUNT) { source = 0; @@ -573,23 +653,26 @@ control_messages(struct gl_context *ctx, sevmax = severity+1; } - for (sev = severity; sev < sevmax; sev++) - for (s = source; s < smax; s++) + for (sev = severity; sev < sevmax; sev++) { + for (s = source; s < smax; s++) { for (t = type; t < tmax; t++) { struct simple_node *node; struct gl_debug_severity *entry; /* change the default for IDs we've never seen before. */ - ctx->Debug.Defaults[gstack][sev][s][t] = enabled; + debug->Defaults[gstack][sev][s][t] = enabled; /* Now change the state of IDs we *have* seen... */ - foreach(node, &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) { + foreach(node, &debug->Namespaces[gstack][s][t].Severity[sev]) { entry = (struct gl_debug_severity *)node; set_message_state(ctx, s, t, entry->ID, enabled); } } + } + } } + /** * Debugging-message namespaces with the source APPLICATION or THIRD_PARTY * require special handling, since the IDs in them are controlled by clients, @@ -621,6 +704,7 @@ control_app_messages(struct gl_context *ctx, GLenum esource, GLenum etype, control_messages(ctx, source, type, severity, enabled); } + /** * This is a generic message control function for use by both * glDebugMessageControlARB and glDebugMessageControl. @@ -658,6 +742,7 @@ message_control(GLenum gl_source, GLenum gl_type, count, ids, enabled); } + /** * This is a generic message insert function. * Validation of source, type and severity parameters should be done @@ -665,7 +750,7 @@ message_control(GLenum gl_source, GLenum gl_type, */ static void message_insert(GLenum source, GLenum type, GLuint id, - GLenum severity, GLint length, const GLchar* buf, + GLenum severity, GLint length, const GLchar *buf, const char *callerstr) { GET_CURRENT_CONTEXT(ctx); @@ -681,20 +766,21 @@ message_insert(GLenum source, GLenum type, GLuint id, return; } - _mesa_log_msg(ctx, - gl_enum_to_debug_source(source), - gl_enum_to_debug_type(type), id, - gl_enum_to_debug_severity(severity), length, buf); + log_msg(ctx, + gl_enum_to_debug_source(source), + gl_enum_to_debug_type(type), id, + gl_enum_to_debug_severity(severity), length, buf); } + /** * This is a generic message insert function for use by both * glGetDebugMessageLogARB and glGetDebugMessageLog. */ static GLuint -get_message_log(GLuint count, GLsizei logSize, GLenum* sources, - GLenum* types, GLenum* ids, GLenum* severities, - GLsizei* lengths, GLchar* messageLog, +get_message_log(GLuint count, GLsizei logSize, GLenum *sources, + GLenum *types, GLenum *ids, GLenum *severities, + GLsizei *lengths, GLchar *messageLog, unsigned caller, const char *callerstr) { GET_CURRENT_CONTEXT(ctx); @@ -711,8 +797,8 @@ get_message_log(GLuint count, GLsizei logSize, GLenum* sources, } for (ret = 0; ret < count; ret++) { - GLsizei written = _mesa_get_msg(ctx, sources, types, ids, severities, - logSize, messageLog, caller); + GLsizei written = get_msg(ctx, sources, types, ids, severities, + logSize, messageLog, caller); if (!written) break; @@ -738,41 +824,52 @@ get_message_log(GLuint count, GLsizei logSize, GLenum* sources, return ret; } + static void do_nothing(GLuint key, void *data, void *userData) { } + +/** + * Free context state pertaining to error/debug state for the given stack + * depth. + */ static void free_errors_data(struct gl_context *ctx, GLint gstack) { + struct gl_debug_state *debug = ctx->Debug; enum mesa_debug_type t; enum mesa_debug_source s; enum mesa_debug_severity sev; + assert(debug); + /* Tear down state for filtering debug messages. */ - for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) + for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) { for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { - _mesa_HashDeleteAll(ctx->Debug.Namespaces[gstack][s][t].IDs, + _mesa_HashDeleteAll(debug->Namespaces[gstack][s][t].IDs, do_nothing, NULL); - _mesa_DeleteHashTable(ctx->Debug.Namespaces[gstack][s][t].IDs); + _mesa_DeleteHashTable(debug->Namespaces[gstack][s][t].IDs); for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) { struct simple_node *node, *tmp; struct gl_debug_severity *entry; foreach_s(node, tmp, - &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) { + &debug->Namespaces[gstack][s][t].Severity[sev]) { entry = (struct gl_debug_severity *)node; free(entry); } } } + } } + void GLAPIENTRY _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, GLint length, - const GLchar* buf) + const GLchar *buf) { const char *callerstr = "glDebugMessageInsert"; @@ -781,14 +878,14 @@ _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id, if (!validate_params(ctx, INSERT, callerstr, source, type, severity)) return; /* GL_INVALID_ENUM */ - message_insert(source, type, id, severity, length, buf, - callerstr); + message_insert(source, type, id, severity, length, buf, callerstr); } + GLuint GLAPIENTRY -_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum* sources, - GLenum* types, GLenum* ids, GLenum* severities, - GLsizei* lengths, GLchar* messageLog) +_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources, + GLenum *types, GLenum *ids, GLenum *severities, + GLsizei *lengths, GLchar *messageLog) { const char *callerstr = "glGetDebugMessageLog"; @@ -796,6 +893,7 @@ _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum* sources, lengths, messageLog, MESSAGE_LOG, callerstr); } + void GLAPIENTRY _mesa_DebugMessageControl(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, @@ -807,28 +905,36 @@ _mesa_DebugMessageControl(GLenum source, GLenum type, GLenum severity, enabled, CONTROL, callerstr); } + void GLAPIENTRY _mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam) { GET_CURRENT_CONTEXT(ctx); - ctx->Debug.Callback = callback; - ctx->Debug.CallbackData = userParam; - ctx->Debug.ARBCallback = GL_FALSE; + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->Callback = callback; + debug->CallbackData = userParam; + debug->ARBCallback = GL_FALSE; + } } + void GLAPIENTRY _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message) { + GET_CURRENT_CONTEXT(ctx); + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); const char *callerstr = "glPushDebugGroup"; int s, t, sev; GLint prevStackDepth; GLint currStackDepth; struct gl_debug_msg *emptySlot; - GET_CURRENT_CONTEXT(ctx); + if (!debug) + return; - if (ctx->Debug.GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) { + if (debug->GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) { _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr); return; } @@ -847,14 +953,14 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, GL_DEBUG_SEVERITY_NOTIFICATION, length, message, callerstr); - prevStackDepth = ctx->Debug.GroupStackDepth; - ctx->Debug.GroupStackDepth++; - currStackDepth = ctx->Debug.GroupStackDepth; + prevStackDepth = debug->GroupStackDepth; + debug->GroupStackDepth++; + currStackDepth = debug->GroupStackDepth; /* pop reuses the message details from push so we store this */ if (length < 0) length = strlen(message); - emptySlot = &ctx->Debug.DebugGroupMsgs[ctx->Debug.GroupStackDepth]; + emptySlot = &debug->DebugGroupMsgs[debug->GroupStackDepth]; store_message_details(emptySlot, gl_enum_to_debug_source(source), gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP), id, @@ -864,60 +970,66 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, /* inherit the control volume of the debug group previously residing on * the top of the debug group stack */ - for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) + for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) { for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { /* copy id settings */ - ctx->Debug.Namespaces[currStackDepth][s][t].IDs = - _mesa_HashClone(ctx->Debug.Namespaces[prevStackDepth][s][t].IDs); + debug->Namespaces[currStackDepth][s][t].IDs = + _mesa_HashClone(debug->Namespaces[prevStackDepth][s][t].IDs); for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) { struct gl_debug_severity *entry, *prevEntry; struct simple_node *node; /* copy default settings for unknown ids */ - ctx->Debug.Defaults[currStackDepth][sev][s][t] = ctx->Debug.Defaults[prevStackDepth][sev][s][t]; + debug->Defaults[currStackDepth][sev][s][t] = + debug->Defaults[prevStackDepth][sev][s][t]; /* copy known id severity settings */ - make_empty_list(&ctx->Debug.Namespaces[currStackDepth][s][t].Severity[sev]); - foreach(node, &ctx->Debug.Namespaces[prevStackDepth][s][t].Severity[sev]) { + make_empty_list(&debug->Namespaces[currStackDepth][s][t].Severity[sev]); + foreach(node, &debug->Namespaces[prevStackDepth][s][t].Severity[sev]) { prevEntry = (struct gl_debug_severity *)node; entry = malloc(sizeof *entry); if (!entry) return; entry->ID = prevEntry->ID; - insert_at_tail(&ctx->Debug.Namespaces[currStackDepth][s][t].Severity[sev], &entry->link); + insert_at_tail(&debug->Namespaces[currStackDepth][s][t].Severity[sev], &entry->link); } } } + } } + void GLAPIENTRY -_mesa_PopDebugGroup() +_mesa_PopDebugGroup(void) { + GET_CURRENT_CONTEXT(ctx); + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); const char *callerstr = "glPopDebugGroup"; struct gl_debug_msg *gdmessage; GLint prevStackDepth; - GET_CURRENT_CONTEXT(ctx); + if (!debug) + return; - if (ctx->Debug.GroupStackDepth <= 0) { + if (debug->GroupStackDepth <= 0) { _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr); return; } - prevStackDepth = ctx->Debug.GroupStackDepth; - ctx->Debug.GroupStackDepth--; + prevStackDepth = debug->GroupStackDepth; + debug->GroupStackDepth--; - gdmessage = &ctx->Debug.DebugGroupMsgs[prevStackDepth]; - /* using _mesa_log_msg() directly here as verification of parameters + gdmessage = &debug->DebugGroupMsgs[prevStackDepth]; + /* using log_msg() directly here as verification of parameters * already done in push */ - _mesa_log_msg(ctx, gdmessage->source, - gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP), - gdmessage->id, - gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION), - gdmessage->length, gdmessage->message); + log_msg(ctx, gdmessage->source, + gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP), + gdmessage->id, + gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION), + gdmessage->length, gdmessage->message); if (gdmessage->message != (char*)out_of_memory) free(gdmessage->message); @@ -928,10 +1040,11 @@ _mesa_PopDebugGroup() free_errors_data(ctx, prevStackDepth); } + void GLAPIENTRY _mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id, GLenum severity, GLint length, - const GLcharARB* buf) + const GLcharARB *buf) { const char *callerstr = "glDebugMessageInsertARB"; @@ -940,14 +1053,14 @@ _mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id, if (!validate_params(ctx, INSERT_ARB, callerstr, source, type, severity)) return; /* GL_INVALID_ENUM */ - message_insert(source, type, id, severity, length, buf, - callerstr); + message_insert(source, type, id, severity, length, buf, callerstr); } + GLuint GLAPIENTRY -_mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources, - GLenum* types, GLenum* ids, GLenum* severities, - GLsizei* lengths, GLcharARB* messageLog) +_mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum *sources, + GLenum *types, GLenum *ids, GLenum *severities, + GLsizei *lengths, GLcharARB *messageLog) { const char *callerstr = "glGetDebugMessageLogARB"; @@ -955,6 +1068,7 @@ _mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources, lengths, messageLog, MESSAGE_LOG_ARB, callerstr); } + void GLAPIENTRY _mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type, GLenum gl_severity, @@ -967,47 +1081,27 @@ _mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type, enabled, CONTROL_ARB, callerstr); } + void GLAPIENTRY _mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, const void *userParam) { GET_CURRENT_CONTEXT(ctx); - ctx->Debug.Callback = callback; - ctx->Debug.CallbackData = userParam; - ctx->Debug.ARBCallback = GL_TRUE; + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + if (debug) { + debug->Callback = callback; + debug->CallbackData = userParam; + debug->ARBCallback = GL_TRUE; + } } + void _mesa_init_errors(struct gl_context *ctx) { - int s, t, sev; - - ctx->Debug.Callback = NULL; - ctx->Debug.SyncOutput = GL_FALSE; - ctx->Debug.Log[0].length = 0; - ctx->Debug.NumMessages = 0; - ctx->Debug.NextMsg = 0; - ctx->Debug.NextMsgLength = 0; - ctx->Debug.GroupStackDepth = 0; - - /* Enable all the messages with severity HIGH or MEDIUM by default. */ - memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE, - sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_HIGH]); - memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE, - sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]); - memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE, - sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_LOW]); - - /* Initialize state for filtering known debug messages. */ - for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) - for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) { - ctx->Debug.Namespaces[0][s][t].IDs = _mesa_NewHashTable(); - assert(ctx->Debug.Namespaces[0][s][t].IDs); - - for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) - make_empty_list(&ctx->Debug.Namespaces[0][s][t].Severity[sev]); - } + /* no-op */ } + /** * Loop through debug group stack tearing down states for * filtering debug messages. @@ -1015,13 +1109,16 @@ _mesa_init_errors(struct gl_context *ctx) void _mesa_free_errors_data(struct gl_context *ctx) { - GLint i; + if (ctx->Debug) { + GLint i; - for (i = 0; i <= ctx->Debug.GroupStackDepth; i++) { - free_errors_data(ctx, i); + for (i = 0; i <= ctx->Debug->GroupStackDepth; i++) { + free_errors_data(ctx, i); + } } } + /**********************************************************************/ /** \name Diagnostics */ /*@{*/ @@ -1077,6 +1174,7 @@ output_if_debug(const char *prefixString, const char *outputString, } } + /** * When a new type of error is recorded, print a message describing * previous errors which were accumulated. @@ -1149,6 +1247,7 @@ _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) } } + static GLboolean should_output(struct gl_context *ctx, GLenum error, const char *fmtString) { @@ -1185,6 +1284,7 @@ should_output(struct gl_context *ctx, GLenum error, const char *fmtString) return GL_FALSE; } + void _mesa_gl_debug(struct gl_context *ctx, GLuint *id, @@ -1202,8 +1302,7 @@ _mesa_gl_debug(struct gl_context *ctx, len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); va_end(args); - _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, type, - *id, severity, len, s); + log_msg(ctx, MESA_DEBUG_SOURCE_API, type, *id, severity, len, s); } @@ -1248,7 +1347,8 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) if (len >= MAX_DEBUG_MESSAGE_LENGTH) { /* Too long error message. Whoever calls _mesa_error should use - * shorter strings. */ + * shorter strings. + */ ASSERT(0); return; } @@ -1268,11 +1368,8 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) /* Log the error via ARB_debug_output if needed.*/ if (do_log) { - _mesa_log_msg(ctx, - MESA_DEBUG_SOURCE_API, - MESA_DEBUG_TYPE_ERROR, - error_msg_id, - MESA_DEBUG_SEVERITY_HIGH, len, s2); + log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR, + error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2); } } @@ -1329,7 +1426,7 @@ _mesa_shader_debug( struct gl_context *ctx, GLenum type, GLuint *id, if (len >= MAX_DEBUG_MESSAGE_LENGTH) len = MAX_DEBUG_MESSAGE_LENGTH - 1; - _mesa_log_msg(ctx, source, type, *id, severity, len, msg); + log_msg(ctx, source, type, *id, severity, len, msg); } /*@}*/ diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h index a837dc8e1..cd414e6b6 100644 --- a/mesalib/src/mesa/main/errors.h +++ b/mesalib/src/mesa/main/errors.h @@ -83,6 +83,9 @@ _mesa_gl_debug(struct gl_context *ctx, } \ } while (0) +struct gl_debug_state * +_mesa_get_debug_state(struct gl_context *ctx); + extern void _mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id, const char *msg, int len); diff --git a/mesalib/src/mesa/main/execmem.c b/mesalib/src/mesa/main/execmem.c index d63bb4a4e..7267cf85f 100644 --- a/mesalib/src/mesa/main/execmem.c +++ b/mesalib/src/mesa/main/execmem.c @@ -32,7 +32,6 @@ #include "imports.h" -#include "glapi/glthread.h" @@ -59,7 +58,7 @@ #define EXEC_HEAP_SIZE (10*1024*1024) -_glthread_DECLARE_STATIC_MUTEX(exec_mutex); +static mtx_t exec_mutex = _MTX_INITIALIZER_NP; static struct mem_block *exec_heap = NULL; static unsigned char *exec_mem = NULL; @@ -93,7 +92,7 @@ _mesa_exec_malloc(GLuint size) struct mem_block *block = NULL; void *addr = NULL; - _glthread_LOCK_MUTEX(exec_mutex); + mtx_lock(&exec_mutex); if (!init_heap()) goto bail; @@ -109,7 +108,7 @@ _mesa_exec_malloc(GLuint size) printf("_mesa_exec_malloc failed\n"); bail: - _glthread_UNLOCK_MUTEX(exec_mutex); + mtx_unlock(&exec_mutex); return addr; } @@ -118,7 +117,7 @@ bail: void _mesa_exec_free(void *addr) { - _glthread_LOCK_MUTEX(exec_mutex); + mtx_lock(&exec_mutex); if (exec_heap) { struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem); @@ -127,7 +126,7 @@ _mesa_exec_free(void *addr) mmFreeMem(block); } - _glthread_UNLOCK_MUTEX(exec_mutex); + mtx_unlock(&exec_mutex); } diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 5f741fbd2..c46d70b20 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -83,6 +83,7 @@ static const struct extension extension_table[] = { { "GL_ARB_arrays_of_arrays", o(ARB_arrays_of_arrays), GL, 2012 }, { "GL_ARB_base_instance", o(ARB_base_instance), GL, 2011 }, { "GL_ARB_blend_func_extended", o(ARB_blend_func_extended), GL, 2009 }, + { "GL_ARB_buffer_storage", o(ARB_buffer_storage), GL, 2013 }, { "GL_ARB_clear_buffer_object", o(dummy_true), GL, 2012 }, { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, { "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 }, @@ -106,7 +107,7 @@ static const struct extension extension_table[] = { { "GL_ARB_framebuffer_sRGB", o(EXT_framebuffer_sRGB), GL, 1998 }, { "GL_ARB_get_program_binary", o(dummy_true), GL, 2010 }, { "GL_ARB_gpu_shader5", o(ARB_gpu_shader5), GL, 2010 }, - { "GL_ARB_half_float_pixel", o(ARB_half_float_pixel), GL, 2003 }, + { "GL_ARB_half_float_pixel", o(dummy_true), GL, 2003 }, { "GL_ARB_half_float_vertex", o(ARB_half_float_vertex), GL, 2008 }, { "GL_ARB_instanced_arrays", o(ARB_instanced_arrays), GL, 2008 }, { "GL_ARB_internalformat_query", o(ARB_internalformat_query), GL, 2011 }, @@ -126,6 +127,7 @@ static const struct extension extension_table[] = { { "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 }, { "GL_ARB_sampler_objects", o(dummy_true), GL, 2009 }, { "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 }, + { "GL_ARB_separate_shader_objects", o(ARB_separate_shader_objects), GL, 2010 }, { "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 }, @@ -401,7 +403,6 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ARB_fragment_program_shadow = GL_TRUE; ctx->Extensions.ARB_fragment_shader = GL_TRUE; ctx->Extensions.ARB_framebuffer_object = GL_TRUE; - ctx->Extensions.ARB_half_float_pixel = GL_TRUE; ctx->Extensions.ARB_half_float_vertex = GL_TRUE; ctx->Extensions.ARB_map_buffer_range = GL_TRUE; ctx->Extensions.ARB_occlusion_query = GL_TRUE; diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index e459e0c63..a9dcc5144 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -89,9 +89,9 @@ delete_dummy_framebuffer(struct gl_framebuffer *fb) void _mesa_init_fbobjects(struct gl_context *ctx) { - _glthread_INIT_MUTEX(DummyFramebuffer.Mutex); - _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex); - _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex); + mtx_init(&DummyFramebuffer.Mutex, mtx_plain); + mtx_init(&DummyRenderbuffer.Mutex, mtx_plain); + mtx_init(&IncompleteFramebuffer.Mutex, mtx_plain); DummyFramebuffer.Delete = delete_dummy_framebuffer; DummyRenderbuffer.Delete = delete_dummy_renderbuffer; IncompleteFramebuffer.Delete = delete_dummy_framebuffer; @@ -484,7 +484,7 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, { struct gl_renderbuffer_attachment *att; - _glthread_LOCK_MUTEX(fb->Mutex); + mtx_lock(&fb->Mutex); att = get_attachment(ctx, fb, attachment); ASSERT(att); @@ -504,7 +504,7 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx, invalidate_framebuffer(fb); - _glthread_UNLOCK_MUTEX(fb->Mutex); + mtx_unlock(&fb->Mutex); } @@ -1352,9 +1352,9 @@ _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers) GLuint name = first + i; renderbuffers[i] = name; /* insert dummy placeholder into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } } @@ -2218,9 +2218,9 @@ _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers) GLuint name = first + i; framebuffers[i] = name; /* insert dummy placeholder into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } } @@ -2433,7 +2433,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, FLUSH_VERTICES(ctx, _NEW_BUFFERS); - _glthread_LOCK_MUTEX(fb->Mutex); + mtx_lock(&fb->Mutex); if (texObj) { if (attachment == GL_DEPTH_ATTACHMENT && texObj == fb->Attachment[BUFFER_STENCIL].Texture && @@ -2491,7 +2491,7 @@ framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, invalidate_framebuffer(fb); - _glthread_UNLOCK_MUTEX(fb->Mutex); + mtx_unlock(&fb->Mutex); } diff --git a/mesalib/src/mesa/main/format_pack.c b/mesalib/src/mesa/main/format_pack.c index dee253c40..2772ff2d3 100644 --- a/mesalib/src/mesa/main/format_pack.c +++ b/mesalib/src/mesa/main/format_pack.c @@ -1936,9 +1936,9 @@ _mesa_get_pack_ubyte_rgba_function(mesa_format format) /* should never convert RGBA to these formats */ table[MESA_FORMAT_S8_UINT_Z24_UNORM] = NULL; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; - table[MESA_FORMAT_Z_UNORM16] = NULL; table[MESA_FORMAT_Z24_UNORM_S8_UINT] = NULL; + table[MESA_FORMAT_Z_UNORM16] = NULL; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; table[MESA_FORMAT_X8Z24_UNORM] = NULL; table[MESA_FORMAT_Z_UNORM32] = NULL; table[MESA_FORMAT_S_UINT8] = NULL; @@ -2099,9 +2099,9 @@ _mesa_get_pack_float_rgba_function(mesa_format format) /* should never convert RGBA to these formats */ table[MESA_FORMAT_S8_UINT_Z24_UNORM] = NULL; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; - table[MESA_FORMAT_Z_UNORM16] = NULL; table[MESA_FORMAT_Z24_UNORM_S8_UINT] = NULL; + table[MESA_FORMAT_Z_UNORM16] = NULL; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = NULL; table[MESA_FORMAT_X8Z24_UNORM] = NULL; table[MESA_FORMAT_Z_UNORM32] = NULL; table[MESA_FORMAT_S_UINT8] = NULL; @@ -2433,8 +2433,8 @@ _mesa_get_pack_float_z_func(mesa_format format) case MESA_FORMAT_S8_UINT_Z24_UNORM: case MESA_FORMAT_X8Z24_UNORM: return pack_float_z_Z24_S8; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return pack_float_z_S8_Z24; case MESA_FORMAT_Z_UNORM16: return pack_float_z_Z16; @@ -2518,8 +2518,8 @@ _mesa_get_pack_uint_z_func(mesa_format format) case MESA_FORMAT_S8_UINT_Z24_UNORM: case MESA_FORMAT_X8Z24_UNORM: return pack_uint_z_Z24_S8; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return pack_uint_z_S8_Z24; case MESA_FORMAT_Z_UNORM16: return pack_uint_z_Z16; @@ -2581,7 +2581,7 @@ _mesa_get_pack_ubyte_stencil_func(mesa_format format) switch (format) { case MESA_FORMAT_S8_UINT_Z24_UNORM: return pack_ubyte_stencil_Z24_S8; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: return pack_ubyte_stencil_S8_Z24; case MESA_FORMAT_S_UINT8: return pack_ubyte_stencil_S8; @@ -2616,8 +2616,8 @@ _mesa_pack_float_z_row(mesa_format format, GLuint n, } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: { /* don't disturb the stencil values */ GLuint *d = ((GLuint *) dst); @@ -2690,8 +2690,8 @@ _mesa_pack_uint_z_row(mesa_format format, GLuint n, } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: { /* don't disturb the stencil values */ GLuint *d = ((GLuint *) dst); @@ -2762,7 +2762,7 @@ _mesa_pack_ubyte_stencil_row(mesa_format format, GLuint n, } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: { /* don't disturb the Z values */ GLuint *d = ((GLuint *) dst); @@ -2803,7 +2803,7 @@ _mesa_pack_uint_24_8_depth_stencil_row(mesa_format format, GLuint n, case MESA_FORMAT_S8_UINT_Z24_UNORM: memcpy(dst, src, n * sizeof(GLuint)); break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: { GLuint *d = ((GLuint *) dst); GLuint i; diff --git a/mesalib/src/mesa/main/format_unpack.c b/mesalib/src/mesa/main/format_unpack.c index 02ad00a9d..276ba556a 100644 --- a/mesalib/src/mesa/main/format_unpack.c +++ b/mesalib/src/mesa/main/format_unpack.c @@ -2366,9 +2366,9 @@ get_unpack_rgba_function(mesa_format format) table[MESA_FORMAT_B10G10R10A2_UINT] = unpack_ARGB2101010_UINT; table[MESA_FORMAT_R10G10B10A2_UINT] = unpack_ABGR2101010_UINT; table[MESA_FORMAT_S8_UINT_Z24_UNORM] = unpack_Z24_S8; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = unpack_S8_Z24; + table[MESA_FORMAT_Z24_UNORM_S8_UINT] = unpack_S8_Z24; table[MESA_FORMAT_Z_UNORM16] = unpack_Z16; - table[MESA_FORMAT_Z24_UNORM_S8_UINT] = unpack_X8_Z24; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = unpack_X8_Z24; table[MESA_FORMAT_X8Z24_UNORM] = unpack_Z24_X8; table[MESA_FORMAT_Z_UNORM32] = unpack_Z32; table[MESA_FORMAT_S_UINT8] = unpack_S8; @@ -3986,8 +3986,8 @@ _mesa_unpack_float_z_row(mesa_format format, GLuint n, case MESA_FORMAT_X8Z24_UNORM: unpack = unpack_float_z_Z24_X8; break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: unpack = unpack_float_z_X8_Z24; break; case MESA_FORMAT_Z_UNORM16: @@ -4091,8 +4091,8 @@ _mesa_unpack_uint_z_row(mesa_format format, GLuint n, case MESA_FORMAT_X8Z24_UNORM: unpack = unpack_uint_z_Z24_X8; break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: unpack = unpack_uint_z_X8_Z24; break; case MESA_FORMAT_Z_UNORM16: @@ -4164,7 +4164,7 @@ _mesa_unpack_ubyte_stencil_row(mesa_format format, GLuint n, case MESA_FORMAT_S8_UINT_Z24_UNORM: unpack_ubyte_s_Z24_S8(src, dst, n); break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: unpack_ubyte_s_S8_Z24(src, dst, n); break; case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: @@ -4188,12 +4188,31 @@ unpack_uint_24_8_depth_stencil_S8_Z24(const GLuint *src, GLuint *dst, GLuint n) } } +static void +unpack_uint_24_8_depth_stencil_Z32_S8X24(const GLuint *src, + GLuint *dst, GLuint n) +{ + GLuint i; + + for (i = 0; i < n; i++) { + /* 8 bytes per pixel (float + uint32) */ + GLfloat zf = ((GLfloat *) src)[i * 2 + 0]; + GLuint z24 = (GLuint) (zf * (GLfloat) 0xffffff); + GLuint s = src[i * 2 + 1] & 0xff; + dst[i] = (z24 << 8) | s; + } +} + static void unpack_uint_24_8_depth_stencil_Z24_S8(const GLuint *src, GLuint *dst, GLuint n) { memcpy(dst, src, n * 4); } +/** + * Unpack depth/stencil returning as GL_UNSIGNED_INT_24_8. + * \param format the source data format + */ void _mesa_unpack_uint_24_8_depth_stencil_row(mesa_format format, GLuint n, const void *src, GLuint *dst) @@ -4202,9 +4221,12 @@ _mesa_unpack_uint_24_8_depth_stencil_row(mesa_format format, GLuint n, case MESA_FORMAT_S8_UINT_Z24_UNORM: unpack_uint_24_8_depth_stencil_Z24_S8(src, dst, n); break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: unpack_uint_24_8_depth_stencil_S8_Z24(src, dst, n); break; + case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: + unpack_uint_24_8_depth_stencil_Z32_S8X24(src, dst, n); + break; default: _mesa_problem(NULL, "bad format %s in _mesa_unpack_uint_24_8_depth_stencil_row", diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index 10731d5a4..f6c399ede 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -439,8 +439,8 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 1, 1, 4 /* BlockWidth/Height,Bytes */ }, { - MESA_FORMAT_Z24_UNORM_X8_UINT, /* Name */ - "MESA_FORMAT_Z24_UNORM_X8_UINT", /* StrName */ + MESA_FORMAT_Z24_UNORM_S8_UINT, /* Name */ + "MESA_FORMAT_Z24_UNORM_S8_UINT", /* StrName */ GL_DEPTH_STENCIL, /* BaseFormat */ GL_UNSIGNED_NORMALIZED, /* DataType */ 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ @@ -457,8 +457,8 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 1, 1, 2 /* BlockWidth/Height,Bytes */ }, { - MESA_FORMAT_Z24_UNORM_S8_UINT, /* Name */ - "MESA_FORMAT_Z24_UNORM_S8_UINT", /* StrName */ + MESA_FORMAT_Z24_UNORM_X8_UINT, /* Name */ + "MESA_FORMAT_Z24_UNORM_X8_UINT", /* StrName */ GL_DEPTH_COMPONENT, /* BaseFormat */ GL_UNSIGNED_NORMALIZED, /* DataType */ 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ @@ -2472,7 +2472,7 @@ _mesa_format_to_type_and_comps(mesa_format format, *comps = 2; return; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: *datatype = GL_UNSIGNED_INT_8_24_REV_MESA; *comps = 2; return; @@ -2482,7 +2482,7 @@ _mesa_format_to_type_and_comps(mesa_format format, *comps = 1; return; - case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: *datatype = GL_UNSIGNED_INT; *comps = 1; return; @@ -3123,14 +3123,14 @@ _mesa_format_matches_format_and_type(mesa_format mesa_format, return format == GL_DEPTH_STENCIL && type == GL_UNSIGNED_INT_24_8 && !swapBytes; case MESA_FORMAT_X8Z24_UNORM: - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: return GL_FALSE; case MESA_FORMAT_Z_UNORM16: return format == GL_DEPTH_COMPONENT && type == GL_UNSIGNED_SHORT && !swapBytes; - case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return GL_FALSE; case MESA_FORMAT_Z_UNORM32: diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 63d9565e3..3102584b6 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -339,33 +339,33 @@ typedef enum /* Type P formats */ /* msb <------ TEXEL BITS -----------> lsb */ /* ---- ---- ---- ---- ---- ---- ---- ---- */ - MESA_FORMAT_A8B8G8R8_UNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_R8G8B8A8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ - MESA_FORMAT_B8G8R8A8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */ - MESA_FORMAT_A8R8G8B8_UNORM, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ - MESA_FORMAT_X8B8G8R8_UNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_R8G8B8X8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ - MESA_FORMAT_B8G8R8X8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR xxxx xxxx */ - MESA_FORMAT_X8R8G8B8_UNORM, /* xxxx xxxx RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_A8B8G8R8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_R8G8B8A8_UNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_B8G8R8A8_UNORM, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_A8R8G8B8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */ + MESA_FORMAT_X8B8G8R8_UNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ + MESA_FORMAT_R8G8B8X8_UNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_B8G8R8X8_UNORM, /* xxxx xxxx RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_X8R8G8B8_UNORM, /* BBBB BBBB GGGG GGGG RRRR RRRR xxxx xxxx */ /* Type A formats */ MESA_FORMAT_BGR_UNORM8, /* uchar[i * 3] = B, [i * 3 + 1] = G, [i *3 + 2] = R */ MESA_FORMAT_RGB_UNORM8, /* uchar[i * 3] = R, [i * 3 + 1] = G, [i *3 + 2] = B */ /* Type P formats */ - MESA_FORMAT_B5G6R5_UNORM, /* BBBB BGGG GGGR RRRR */ - MESA_FORMAT_R5G6B5_UNORM, /* RRRR RGGG GGGB BBBB */ - MESA_FORMAT_B4G4R4A4_UNORM, /* BBBB GGGG RRRR AAAA */ - MESA_FORMAT_A4R4G4B4_UNORM, /* AAAA RRRR GGGG BBBB */ - MESA_FORMAT_A1B5G5R5_UNORM, /* ABBB BBGG GGGR RRRR */ - MESA_FORMAT_B5G5R5A1_UNORM, /* BBBB BGGG GGRR RRRA */ - MESA_FORMAT_A1R5G5B5_UNORM, /* ARRR RRGG GGGB BBBB */ - MESA_FORMAT_L4A4_UNORM, /* LLLL AAAA */ - MESA_FORMAT_L8A8_UNORM, /* LLLL LLLL AAAA AAAA */ - MESA_FORMAT_A8L8_UNORM, /* AAAA AAAA LLLL LLLL */ - MESA_FORMAT_L16A16_UNORM, /* LLLL LLLL LLLL LLLL AAAA AAAA AAAA AAAA */ - MESA_FORMAT_A16L16_UNORM, /* AAAA AAAA AAAA AAAA LLLL LLLL LLLL LLLL */ - MESA_FORMAT_B2G3R3_UNORM, /* BBGG GRRR */ + MESA_FORMAT_B5G6R5_UNORM, /* RRRR RGGG GGGB BBBB */ + MESA_FORMAT_R5G6B5_UNORM, /* BBBB BGGG GGGR RRRR */ + MESA_FORMAT_B4G4R4A4_UNORM, /* AAAA RRRR GGGG BBBB */ + MESA_FORMAT_A4R4G4B4_UNORM, /* BBBB GGGG RRRR AAAA */ + MESA_FORMAT_A1B5G5R5_UNORM, /* RRRR RGGG GGBB BBBA */ + MESA_FORMAT_B5G5R5A1_UNORM, /* ARRR RRGG GGGB BBBB */ + MESA_FORMAT_A1R5G5B5_UNORM, /* BBBB BGGG GGRR RRRA */ + MESA_FORMAT_L4A4_UNORM, /* AAAA LLLL */ + MESA_FORMAT_L8A8_UNORM, /* AAAA AAAA LLLL LLLL */ + MESA_FORMAT_A8L8_UNORM, /* LLLL LLLL AAAA AAAA */ + MESA_FORMAT_L16A16_UNORM, /* AAAA AAAA AAAA AAAA LLLL LLLL LLLL LLLL */ + MESA_FORMAT_A16L16_UNORM, /* LLLL LLLL LLLL LLLL AAAA AAAA AAAA AAAA */ + MESA_FORMAT_B2G3R3_UNORM, /* RRRG GGBB */ /* Type A formats */ MESA_FORMAT_A_UNORM8, /* uchar[i] = A */ @@ -383,25 +383,25 @@ typedef enum MESA_FORMAT_R_UNORM8, /* uchar[i] = R */ /* Type P formats */ - MESA_FORMAT_R8G8_UNORM, /* RRRR RRRR GGGG GGGG */ - MESA_FORMAT_G8R8_UNORM, /* GGGG GGGG RRRR RRRR */ + MESA_FORMAT_R8G8_UNORM, /* GGGG GGGG RRRR RRRR */ + MESA_FORMAT_G8R8_UNORM, /* RRRR RRRR GGGG GGGG */ /* Type A format(s) */ MESA_FORMAT_R_UNORM16, /* ushort[i] = R */ /* Type P formats */ - MESA_FORMAT_R16G16_UNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ - MESA_FORMAT_G16R16_UNORM, /* GGGG GGGG GGGG GGGG RRRR RRRR RRRR RRRR */ - MESA_FORMAT_B10G10R10A2_UNORM,/* BBBB BBBB BBGG GGGG GGGG RRRR RRRR RRAA */ - MESA_FORMAT_S8_UINT_Z24_UNORM,/* SSSS SSSS ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ - MESA_FORMAT_Z24_UNORM_X8_UINT,/* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ xxxx xxxx */ + MESA_FORMAT_R16G16_UNORM, /* GGGG GGGG GGGG GGGG RRRR RRRR RRRR RRRR */ + MESA_FORMAT_G16R16_UNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ + MESA_FORMAT_B10G10R10A2_UNORM,/* AARR RRRR RRRR GGGG GGGG GGBB BBBB BBBB */ + MESA_FORMAT_S8_UINT_Z24_UNORM,/* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ SSSS SSSS */ + MESA_FORMAT_Z24_UNORM_S8_UINT,/* SSSS SSSS ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ /* Type A format(s) */ MESA_FORMAT_Z_UNORM16, /* ushort[i] = Z */ /* Type P formats */ - MESA_FORMAT_Z24_UNORM_S8_UINT,/* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ SSSS SSSS */ - MESA_FORMAT_X8Z24_UNORM, /* xxxx xxxx ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ + MESA_FORMAT_Z24_UNORM_X8_UINT,/* xxxx xxxx ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ */ + MESA_FORMAT_X8Z24_UNORM, /* ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ xxxx xxxx */ /* Type A formats */ MESA_FORMAT_Z_UNORM32, /* uint[i] = Z */ @@ -416,14 +416,14 @@ typedef enum MESA_FORMAT_BGR_SRGB8, /* uchar[i * 3] = B, [i * 3 + 1] = G, [i *3 + 2] = R */ /* Type P formats */ - MESA_FORMAT_A8B8G8R8_SRGB, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR*/ - MESA_FORMAT_B8G8R8A8_SRGB, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */ + MESA_FORMAT_A8B8G8R8_SRGB, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_B8G8R8A8_SRGB, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ /* Type A format(s) */ MESA_FORMAT_L_SRGB8, /* uchar[i] = L */ /* Type P formats */ - MESA_FORMAT_L8A8_SRGB, /* LLLL LLLL AAAA AAAA */ + MESA_FORMAT_L8A8_SRGB, /* AAAA AAAA LLLL LLLL */ /* Type C formats */ MESA_FORMAT_SRGB_DXT1, @@ -548,16 +548,16 @@ typedef enum MESA_FORMAT_R_SNORM8, /* char[i] = R */ /* Type P formats */ - MESA_FORMAT_R8G8_SNORM, /* RRRR RRRR GGGG GGGG */ - MESA_FORMAT_X8B8G8R8_SNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_A8B8G8R8_SNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ - MESA_FORMAT_R8G8B8A8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_R8G8_SNORM, /* GGGG GGGG RRRR RRRR */ + MESA_FORMAT_X8B8G8R8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ + MESA_FORMAT_A8B8G8R8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_R8G8B8A8_SNORM, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ /* Type A format(s) */ MESA_FORMAT_R_SNORM16, /* short[i] = R */ /* Type P format(s) */ - MESA_FORMAT_R16G16_SNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ + MESA_FORMAT_R16G16_SNORM, /* GGGG GGGG GGGG GGGG RRRR RRRR RRRR RRRR */ /* Type A format(s) */ MESA_FORMAT_RGB_SNORM16, /* short[i * 3] = R, [i * 3 + 1] = G, [i *3 + 2] = B */ @@ -597,7 +597,7 @@ typedef enum MESA_FORMAT_L_SNORM8, /* char[i] = L */ /* Type P format(s) */ - MESA_FORMAT_L8A8_SNORM, /* LLLL LLLL AAAA AAAA */ + MESA_FORMAT_L8A8_SNORM, /* AAAA AAAA LLLL LLLL */ /* Type A format(s) */ MESA_FORMAT_I_SNORM8, /* char[i] = I */ @@ -608,21 +608,21 @@ typedef enum /* Type P format(s) */ MESA_FORMAT_R9G9B9E5_FLOAT, - MESA_FORMAT_R11G11B10_FLOAT, + MESA_FORMAT_R11G11B10_FLOAT, /* BBBB BBBB BBGG GGGG GGGG GRRR RRRR RRRR */ /* Type A format(s) */ MESA_FORMAT_Z_FLOAT32, /* Type P formats */ - MESA_FORMAT_Z32_FLOAT_S8X24_UINT, + MESA_FORMAT_Z32_FLOAT_S8X24_UINT, /* (float, x24s8) */ - MESA_FORMAT_B10G10R10A2_UINT, - MESA_FORMAT_R10G10B10A2_UINT, + MESA_FORMAT_B10G10R10A2_UINT, /* AARR RRRR RRRR GGGG GGGG GGBB BBBB BBBB */ + MESA_FORMAT_R10G10B10A2_UINT, /* AABB BBBB BBBB GGGG GGGG GGRR RRRR RRRR */ - MESA_FORMAT_B4G4R4X4_UNORM, /* BBBB GGGG RRRR xxxx */ - MESA_FORMAT_B5G5R5X1_UNORM, /* BBBB BGGG GGRR RRRx */ - MESA_FORMAT_R8G8B8X8_SNORM, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ - MESA_FORMAT_R8G8B8X8_SRGB, /* RRRR RRRR GGGG GGGG BBBB BBBB xxxx xxxx */ + MESA_FORMAT_B4G4R4X4_UNORM, /* xxxx RRRR GGGG BBBB */ + MESA_FORMAT_B5G5R5X1_UNORM, /* xRRR RRGG GGGB BBBB */ + MESA_FORMAT_R8G8B8X8_SNORM, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_R8G8B8X8_SRGB, /* xxxx xxxx BBBB BBBB GGGG GGGG RRRR RRRR */ /* Type A formats */ MESA_FORMAT_RGBX_UINT8, /* uchar[i * 4] = R, [i * 4 + 1] = G, [i * 4 + 2] = B, [i * 4 + 3] = x */ @@ -643,9 +643,9 @@ typedef enum MESA_FORMAT_RGBX_SINT32, /* ... */ /* Type P formats */ - MESA_FORMAT_R10G10B10A2_UNORM, - MESA_FORMAT_G8R8_SNORM, - MESA_FORMAT_G16R16_SNORM, + MESA_FORMAT_R10G10B10A2_UNORM, /* AABB BBBB BBBB GGGG GGGG GGRR RRRR RRRR */ + MESA_FORMAT_G8R8_SNORM, /* RRRR RRRR GGGG GGGG */ + MESA_FORMAT_G16R16_SNORM, /* RRRR RRRR RRRR RRRR GGGG GGGG GGGG GGGG */ MESA_FORMAT_COUNT } mesa_format; diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 54eeda2b2..7416bb118 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -130,7 +130,7 @@ _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, memset(fb, 0, sizeof(struct gl_framebuffer)); - _glthread_INIT_MUTEX(fb->Mutex); + mtx_init(&fb->Mutex, mtx_plain); fb->RefCount = 1; @@ -182,7 +182,7 @@ _mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name) fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; fb->_ColorReadBufferIndex = BUFFER_COLOR0; fb->Delete = _mesa_destroy_framebuffer; - _glthread_INIT_MUTEX(fb->Mutex); + mtx_init(&fb->Mutex, mtx_plain); } @@ -213,7 +213,7 @@ _mesa_free_framebuffer_data(struct gl_framebuffer *fb) assert(fb); assert(fb->RefCount == 0); - _glthread_DESTROY_MUTEX(fb->Mutex); + mtx_destroy(&fb->Mutex); for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; @@ -244,11 +244,11 @@ _mesa_reference_framebuffer_(struct gl_framebuffer **ptr, GLboolean deleteFlag = GL_FALSE; struct gl_framebuffer *oldFb = *ptr; - _glthread_LOCK_MUTEX(oldFb->Mutex); + mtx_lock(&oldFb->Mutex); ASSERT(oldFb->RefCount > 0); oldFb->RefCount--; deleteFlag = (oldFb->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldFb->Mutex); + mtx_unlock(&oldFb->Mutex); if (deleteFlag) oldFb->Delete(oldFb); @@ -258,9 +258,9 @@ _mesa_reference_framebuffer_(struct gl_framebuffer **ptr, assert(!*ptr); if (fb) { - _glthread_LOCK_MUTEX(fb->Mutex); + mtx_lock(&fb->Mutex); fb->RefCount++; - _glthread_UNLOCK_MUTEX(fb->Mutex); + mtx_unlock(&fb->Mutex); *ptr = fb; } } diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 54f7d7745..b1908515c 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -28,6 +28,7 @@ #include "blend.h" #include "enable.h" #include "enums.h" +#include "errors.h" #include "extensions.h" #include "get.h" #include "macros.h" @@ -973,6 +974,26 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu _mesa_problem(ctx, "driver doesn't implement GetTimestamp"); } break; + /* GL_KHR_DEBUG */ + case GL_DEBUG_LOGGED_MESSAGES: + { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + v->value_int = debug ? debug->NumMessages : 0; + } + break; + case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH: + { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + v->value_int = debug ? debug->NextMsgLength : 0; + } + break; + case GL_DEBUG_GROUP_STACK_DEPTH: + { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + v->value_int = debug ? debug->GroupStackDepth : 0; + } + break; + /* GL_ARB_shader_atomic_counters */ case GL_ATOMIC_COUNTER_BUFFER_BINDING: v->value_int = ctx->AtomicBuffer->Name; diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index f47cbd881..674d0032a 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -698,13 +698,13 @@ descriptor=[ [ "RESET_NOTIFICATION_STRATEGY_ARB", "CONTEXT_ENUM(Const.ResetStrategy), NO_EXTRA" ], # GL_KHR_debug (GL 4.3)/ GL_ARB_debug_output - [ "DEBUG_LOGGED_MESSAGES", "CONTEXT_INT(Debug.NumMessages), NO_EXTRA" ], - [ "DEBUG_NEXT_LOGGED_MESSAGE_LENGTH", "CONTEXT_INT(Debug.NextMsgLength), NO_EXTRA" ], + [ "DEBUG_LOGGED_MESSAGES", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], + [ "DEBUG_NEXT_LOGGED_MESSAGE_LENGTH", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], [ "MAX_DEBUG_LOGGED_MESSAGES", "CONST(MAX_DEBUG_LOGGED_MESSAGES), NO_EXTRA" ], [ "MAX_DEBUG_MESSAGE_LENGTH", "CONST(MAX_DEBUG_MESSAGE_LENGTH), NO_EXTRA" ], [ "MAX_LABEL_LENGTH", "CONST(MAX_LABEL_LENGTH), NO_EXTRA" ], [ "MAX_DEBUG_GROUP_STACK_DEPTH", "CONST(MAX_DEBUG_GROUP_STACK_DEPTH), NO_EXTRA" ], - [ "DEBUG_GROUP_STACK_DEPTH", "CONTEXT_INT(Debug.GroupStackDepth), NO_EXTRA" ], + [ "DEBUG_GROUP_STACK_DEPTH", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], [ "MAX_DUAL_SOURCE_DRAW_BUFFERS", "CONTEXT_INT(Const.MaxDualSourceDrawBuffers), extra_ARB_blend_func_extended" ], diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c index 674126702..3ac62d402 100644 --- a/mesalib/src/mesa/main/getstring.c +++ b/mesalib/src/mesa/main/getstring.c @@ -253,14 +253,22 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params ) *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr; break; case GL_DEBUG_CALLBACK_FUNCTION_ARB: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_pname; - *params = (GLvoid *) ctx->Debug.Callback; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + *params = debug ? (void *) debug->Callback : NULL; + } break; case GL_DEBUG_CALLBACK_USER_PARAM_ARB: - if (!_mesa_is_desktop_gl(ctx)) + if (!_mesa_is_desktop_gl(ctx)) { goto invalid_pname; - *params = (GLvoid *) ctx->Debug.CallbackData; + } + else { + struct gl_debug_state *debug = _mesa_get_debug_state(ctx); + *params = debug ? (void *) debug->CallbackData : NULL; + } break; default: goto invalid_pname; @@ -326,7 +334,7 @@ _mesa_GetGraphicsResetStatusARB( void ) */ status = ctx->Driver.GetGraphicsResetStatus(ctx); - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); /* If this context has not been affected by a GPU reset, check to see if * some other context in the share group has been affected by a reset. @@ -340,7 +348,7 @@ _mesa_GetGraphicsResetStatusARB( void ) } ctx->ShareGroupReset = ctx->Shared->ShareGroupReset; - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API)) diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 7d4a31057..77cf26337 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -1323,10 +1323,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1349,10 +1347,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1368,10 +1364,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1389,14 +1383,12 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_UNSIGNED_BYTE_2_3_3_REV: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_HALF_FLOAT: return GL_NO_ERROR; case GL_UNSIGNED_INT_2_10_10_10_REV: /* OK by GL_EXT_texture_type_2_10_10_10_REV */ return (ctx->API == API_OPENGLES2) ? GL_NO_ERROR : GL_INVALID_ENUM; - case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; case GL_UNSIGNED_INT_5_9_9_9_REV: return ctx->Extensions.EXT_texture_shared_exponent ? GL_NO_ERROR : GL_INVALID_ENUM; @@ -1419,10 +1411,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } @@ -1446,10 +1436,8 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_UNSIGNED_INT_8_8_8_8_REV: case GL_UNSIGNED_INT_10_10_10_2: case GL_UNSIGNED_INT_2_10_10_10_REV: - return GL_NO_ERROR; case GL_HALF_FLOAT: - return ctx->Extensions.ARB_half_float_pixel - ? GL_NO_ERROR : GL_INVALID_ENUM; + return GL_NO_ERROR; default: return GL_INVALID_ENUM; } diff --git a/mesalib/src/mesa/main/hash.c b/mesalib/src/mesa/main/hash.c index b31fd4839..4c92005e0 100644 --- a/mesalib/src/mesa/main/hash.c +++ b/mesalib/src/mesa/main/hash.c @@ -36,7 +36,6 @@ #include "glheader.h" #include "imports.h" -#include "glapi/glthread.h" #include "hash.h" #include "hash_table.h" @@ -59,8 +58,8 @@ struct _mesa_HashTable { struct hash_table *ht; GLuint MaxKey; /**< highest key inserted so far */ - _glthread_Mutex Mutex; /**< mutual exclusion lock */ - _glthread_Mutex WalkMutex; /**< for _mesa_HashWalk() */ + mtx_t Mutex; /**< mutual exclusion lock */ + mtx_t WalkMutex; /**< for _mesa_HashWalk() */ GLboolean InDeleteAll; /**< Debug check */ /** Value that would be in the table for DELETED_KEY_VALUE. */ void *deleted_key_data; @@ -117,8 +116,8 @@ _mesa_NewHashTable(void) if (table) { table->ht = _mesa_hash_table_create(NULL, uint_key_compare); _mesa_hash_table_set_deleted_key(table->ht, uint_key(DELETED_KEY_VALUE)); - _glthread_INIT_MUTEX(table->Mutex); - _glthread_INIT_MUTEX(table->WalkMutex); + mtx_init(&table->Mutex, mtx_plain); + mtx_init(&table->WalkMutex, mtx_plain); } return table; } @@ -144,8 +143,8 @@ _mesa_DeleteHashTable(struct _mesa_HashTable *table) _mesa_hash_table_destroy(table->ht, NULL); - _glthread_DESTROY_MUTEX(table->Mutex); - _glthread_DESTROY_MUTEX(table->WalkMutex); + mtx_destroy(&table->Mutex); + mtx_destroy(&table->WalkMutex); free(table); } @@ -187,9 +186,9 @@ _mesa_HashLookup(struct _mesa_HashTable *table, GLuint key) { void *res; assert(table); - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); res = _mesa_HashLookup_unlocked(table, key); - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return res; } @@ -211,7 +210,7 @@ _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) assert(table); assert(key); - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); if (key > table->MaxKey) table->MaxKey = key; @@ -227,7 +226,7 @@ _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) } } - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); } @@ -256,14 +255,14 @@ _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key) return; } - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); if (key == DELETED_KEY_VALUE) { table->deleted_key_data = NULL; } else { entry = _mesa_hash_table_search(table->ht, uint_hash(key), uint_key(key)); _mesa_hash_table_remove(table->ht, entry); } - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); } @@ -286,7 +285,7 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, ASSERT(table); ASSERT(callback); - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); table->InDeleteAll = GL_TRUE; hash_table_foreach(table->ht, entry) { callback((uintptr_t)entry->key, entry->data, userData); @@ -297,7 +296,7 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, table->deleted_key_data = NULL; } table->InDeleteAll = GL_FALSE; - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); } @@ -315,7 +314,7 @@ _mesa_HashClone(const struct _mesa_HashTable *table) struct _mesa_HashTable *clonetable; ASSERT(table); - _glthread_LOCK_MUTEX(table2->Mutex); + mtx_lock(&table2->Mutex); clonetable = _mesa_NewHashTable(); assert(clonetable); @@ -323,7 +322,7 @@ _mesa_HashClone(const struct _mesa_HashTable *table) _mesa_HashInsert(clonetable, (GLint)(uintptr_t)entry->key, entry->data); } - _glthread_UNLOCK_MUTEX(table2->Mutex); + mtx_unlock(&table2->Mutex); return clonetable; } @@ -352,13 +351,13 @@ _mesa_HashWalk(const struct _mesa_HashTable *table, ASSERT(table); ASSERT(callback); - _glthread_LOCK_MUTEX(table2->WalkMutex); + mtx_lock(&table2->WalkMutex); hash_table_foreach(table->ht, entry) { callback((uintptr_t)entry->key, entry->data, userData); } if (table->deleted_key_data) callback(DELETED_KEY_VALUE, table->deleted_key_data, userData); - _glthread_UNLOCK_MUTEX(table2->WalkMutex); + mtx_unlock(&table2->WalkMutex); } static void @@ -398,10 +397,10 @@ GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) { const GLuint maxKey = ~((GLuint) 0) - 1; - _glthread_LOCK_MUTEX(table->Mutex); + mtx_lock(&table->Mutex); if (maxKey - numKeys > table->MaxKey) { /* the quick solution */ - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return table->MaxKey + 1; } else { @@ -419,13 +418,13 @@ _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) /* this key not in use, check if we've found enough */ freeCount++; if (freeCount == numKeys) { - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return freeStart; } } } /* cannot allocate a block of numKeys consecutive keys */ - _glthread_UNLOCK_MUTEX(table->Mutex); + mtx_unlock(&table->Mutex); return 0; } } diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index d79e2a339..9e221cccb 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -132,7 +132,7 @@ typedef union { GLfloat f; GLint i; GLuint u; } fi_type; #define atanhf(f) ((float) atanh(f)) #endif -#if defined(_MSC_VER) +#if defined(_MSC_VER) && (_MSC_VER < 1800) /* Not req'd on VS2013 and above */ static inline float truncf(float x) { return x < 0.0f ? ceilf(x) : floorf(x); } static inline float exp2f(float x) { return powf(2.0f, x); } static inline float log2f(float x) { return logf(x) * 1.442695041f; } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index ceabd9df7..bbc377280 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1190,7 +1190,7 @@ struct gl_sampler_object */ struct gl_texture_object { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ GLint RefCount; /**< reference count */ GLuint Name; /**< the user-visible texture object ID */ GLchar *Label; /**< GL_KHR_debug */ @@ -1439,28 +1439,44 @@ struct gl_viewport_attrib }; +typedef enum { + MAP_USER, + MAP_INTERNAL, + + MAP_COUNT +} gl_map_buffer_index; + + +/** + * Fields describing a mapped buffer range. + */ +struct gl_buffer_mapping { + GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */ + GLvoid *Pointer; /**< User-space address of mapping */ + GLintptr Offset; /**< Mapped offset */ + GLsizeiptr Length; /**< Mapped length */ +}; + + /** * GL_ARB_vertex/pixel_buffer_object buffer object */ struct gl_buffer_object { - _glthread_Mutex Mutex; + mtx_t Mutex; GLint RefCount; GLuint Name; GLchar *Label; /**< GL_KHR_debug */ GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */ + GLbitfield StorageFlags; /**< GL_MAP_PERSISTENT_BIT, etc. */ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */ - /** Fields describing a mapped buffer */ - /*@{*/ - GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */ - GLvoid *Pointer; /**< User-space address of mapping */ - GLintptr Offset; /**< Mapped offset */ - GLsizeiptr Length; /**< Mapped length */ - /*@}*/ GLboolean DeletePending; /**< true if buffer object is removed from the hash */ GLboolean Written; /**< Ever written to? (for debugging) */ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */ + GLboolean Immutable; /**< GL_ARB_buffer_storage */ + + struct gl_buffer_mapping Mappings[MAP_COUNT]; }; @@ -1560,7 +1576,7 @@ struct gl_vertex_array_object GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; - _glthread_Mutex Mutex; + mtx_t Mutex; /** * Does the VAO use ARB semantics or Apple semantics? @@ -2013,6 +2029,7 @@ typedef enum SYSTEM_VALUE_SAMPLE_ID, /**< Fragment shader only */ SYSTEM_VALUE_SAMPLE_POS, /**< Fragment shader only */ SYSTEM_VALUE_SAMPLE_MASK_IN, /**< Fragment shader only */ + SYSTEM_VALUE_INVOCATION_ID, /**< Geometry shader only */ SYSTEM_VALUE_MAX /**< Number of values */ } gl_system_value; @@ -2143,6 +2160,7 @@ struct gl_geometry_program GLint VerticesIn; GLint VerticesOut; + GLint Invocations; GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */ @@ -2418,6 +2436,11 @@ struct gl_shader */ struct { GLint VerticesOut; + /** + * 0 - Invocations count not declared in shader, or + * 1 .. MAX_GEOMETRY_SHADER_INVOCATIONS + */ + GLint Invocations; /** * GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES, or * GL_TRIANGLES_ADJACENCY, or PRIM_UNKNOWN if it's not set in this @@ -2579,6 +2602,12 @@ struct gl_shader_program */ GLboolean InternalSeparateShader; + /** + * Indicates whether program can be bound for individual pipeline stages + * using UseProgramStages after it is next linked. + */ + GLboolean SeparateShader; + GLuint NumShaders; /**< number of attached shaders */ struct gl_shader **Shaders; /**< List of attached the shaders */ @@ -2627,6 +2656,10 @@ struct gl_shader_program struct { GLint VerticesIn; GLint VerticesOut; + /** + * 1 .. MAX_GEOMETRY_SHADER_INVOCATIONS + */ + GLint Invocations; GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */ @@ -2746,9 +2779,19 @@ struct gl_shader_program /** * Context state for GLSL vertex/fragment shaders. + * Extended to support pipeline object */ -struct gl_shader_state +struct gl_pipeline_object { + /** Name of the pipeline object as received from glGenProgramPipelines. + * It would be 0 for shaders without separate shader objects. + */ + GLuint Name; + + GLint RefCount; + + mtx_t Mutex; + /** * Programs used for rendering * @@ -2768,8 +2811,21 @@ struct gl_shader_state struct gl_shader_program *ActiveProgram; GLbitfield Flags; /**< Mask of GLSL_x flags */ + + GLboolean EverBound; /**< Has the pipeline object been created */ }; +/** + * Context state for GLSL pipeline shaders. + */ +struct gl_pipeline_shader_state +{ + /** Currently bound pipeline object. See _mesa_BindProgramPipeline() */ + struct gl_pipeline_object *Current; + + /** Pipeline objects */ + struct _mesa_HashTable *Objects; +}; /** * Compiler options for a single GLSL shaders type @@ -2871,7 +2927,7 @@ struct gl_sync_object */ struct gl_shared_state { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ GLint RefCount; /**< Reference count */ struct _mesa_HashTable *DisplayList; /**< Display lists hash table */ struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */ @@ -2889,7 +2945,7 @@ struct gl_shared_state * \todo Improve the granularity of locking. */ /*@{*/ - _glthread_Mutex TexMutex; /**< texobj thread safety */ + mtx_t TexMutex; /**< texobj thread safety */ GLuint TextureStateStamp; /**< state notification for shared tex */ /*@}*/ @@ -2946,7 +3002,7 @@ struct gl_shared_state */ struct gl_renderbuffer { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ GLuint ClassID; /**< Useful for drivers */ GLuint Name; GLchar *Label; /**< GL_KHR_debug */ @@ -3024,7 +3080,7 @@ struct gl_renderbuffer_attachment */ struct gl_framebuffer { - _glthread_Mutex Mutex; /**< for thread safety */ + mtx_t Mutex; /**< for thread safety */ /** * If zero, this is a window system framebuffer. If non-zero, this * is a FBO framebuffer; note that for some devices (i.e. those with @@ -3433,6 +3489,7 @@ struct gl_extensions GLboolean ARB_arrays_of_arrays; GLboolean ARB_base_instance; GLboolean ARB_blend_func_extended; + GLboolean ARB_buffer_storage; GLboolean ARB_color_buffer_float; GLboolean ARB_compute_shader; GLboolean ARB_conservative_depth; @@ -3451,7 +3508,6 @@ struct gl_extensions GLboolean ARB_explicit_attrib_location; GLboolean ARB_geometry_shader4; GLboolean ARB_gpu_shader5; - GLboolean ARB_half_float_pixel; GLboolean ARB_half_float_vertex; GLboolean ARB_instanced_arrays; GLboolean ARB_internalformat_query; @@ -3461,6 +3517,7 @@ struct gl_extensions GLboolean ARB_point_sprite; GLboolean ARB_sample_shading; GLboolean ARB_seamless_cube_map; + GLboolean ARB_separate_shader_objects; GLboolean ARB_shader_atomic_counters; GLboolean ARB_shader_bit_encoding; GLboolean ARB_shader_image_load_store; @@ -4070,7 +4127,8 @@ struct gl_context struct gl_geometry_program_state GeometryProgram; struct gl_ati_fragment_shader_state ATIFragmentShader; - struct gl_shader_state Shader; /**< GLSL shader object state */ + struct gl_pipeline_shader_state Pipeline; /**< GLSL pipeline shader object state */ + struct gl_pipeline_object Shader; /**< GLSL shader object state */ struct gl_shader_compiler_options ShaderCompilerOptions[MESA_SHADER_STAGES]; struct gl_query_state Query; /**< occlusion, timer queries */ @@ -4132,7 +4190,7 @@ struct gl_context GLuint ErrorDebugCount; /* GL_ARB_debug_output/GL_KHR_debug */ - struct gl_debug_state Debug; + struct gl_debug_state *Debug; GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */ GLbitfield NewState; /**< bitwise-or of _NEW_* flags */ diff --git a/mesalib/src/mesa/main/pbo.c b/mesalib/src/mesa/main/pbo.c index 400cec3f0..a0d61a643 100644 --- a/mesalib/src/mesa/main/pbo.c +++ b/mesalib/src/mesa/main/pbo.c @@ -149,7 +149,8 @@ _mesa_map_pbo_source(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -201,7 +202,7 @@ _mesa_map_validate_pbo_source(struct gl_context *ctx, return ptr; } - if (_mesa_bufferobj_mapped(unpack->BufferObj)) { + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); return NULL; @@ -221,7 +222,7 @@ _mesa_unmap_pbo_source(struct gl_context *ctx, { ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } } @@ -246,7 +247,8 @@ _mesa_map_pbo_dest(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, pack->BufferObj->Size, GL_MAP_WRITE_BIT, - pack->BufferObj); + pack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -297,7 +299,7 @@ _mesa_map_validate_pbo_dest(struct gl_context *ctx, return ptr; } - if (_mesa_bufferobj_mapped(unpack->BufferObj)) { + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); return NULL; @@ -317,7 +319,7 @@ _mesa_unmap_pbo_dest(struct gl_context *ctx, { ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(pack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, pack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL); } } @@ -351,7 +353,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, dimensions); @@ -393,7 +396,8 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, packing->BufferObj->Size, GL_MAP_READ_BIT, - packing->BufferObj); + packing->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, dimensions); @@ -413,6 +417,6 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx, const struct gl_pixelstore_attrib *unpack) { if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } } diff --git a/mesalib/src/mesa/main/pipelineobj.c b/mesalib/src/mesa/main/pipelineobj.c new file mode 100644 index 000000000..27012df72 --- /dev/null +++ b/mesalib/src/mesa/main/pipelineobj.c @@ -0,0 +1,445 @@ +/* + * Mesa 3-D graphics library + * + * Copyright © 2013 Gregory Hainaut + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * \file pipelineobj.c + * \author Hainaut Gregory + * + * Implementation of pipeline object related API functions. Based on + * GL_ARB_separate_shader_objects extension. + */ + +#include "main/glheader.h" +#include "main/context.h" +#include "main/dispatch.h" +#include "main/enums.h" +#include "main/hash.h" +#include "main/mtypes.h" +#include "main/pipelineobj.h" +#include "main/shaderapi.h" +#include "main/shaderobj.h" +#include "main/transformfeedback.h" +#include "main/uniforms.h" +#include "program/program.h" +#include "program/prog_parameter.h" +#include "ralloc.h" +#include +#include "../glsl/glsl_parser_extras.h" +#include "../glsl/ir_uniform.h" + +/** + * Delete a pipeline object. + */ +void +_mesa_delete_pipeline_object(struct gl_context *ctx, + struct gl_pipeline_object *obj) +{ + unsigned i; + + _mesa_reference_shader_program(ctx, &obj->_CurrentFragmentProgram, NULL); + + for (i = 0; i < MESA_SHADER_STAGES; i++) + _mesa_reference_shader_program(ctx, &obj->CurrentProgram[i], NULL); + + _mesa_reference_shader_program(ctx, &obj->ActiveProgram, NULL); + mtx_destroy(&obj->Mutex); + ralloc_free(obj); +} + +/** + * Allocate and initialize a new pipeline object. + */ +static struct gl_pipeline_object * +_mesa_new_pipeline_object(struct gl_context *ctx, GLuint name) +{ + struct gl_pipeline_object *obj = rzalloc(NULL, struct gl_pipeline_object); + if (obj) { + obj->Name = name; + mtx_init(&obj->Mutex, mtx_plain); + obj->RefCount = 1; + obj->Flags = _mesa_get_shader_flags(); + } + + return obj; +} + +/** + * Initialize pipeline object state for given context. + */ +void +_mesa_init_pipeline(struct gl_context *ctx) +{ + ctx->Pipeline.Objects = _mesa_NewHashTable(); + + ctx->Pipeline.Current = NULL; +} + + +/** + * Callback for deleting a pipeline object. Called by _mesa_HashDeleteAll(). + */ +static void +delete_pipelineobj_cb(GLuint id, void *data, void *userData) +{ + struct gl_pipeline_object *obj = (struct gl_pipeline_object *) data; + struct gl_context *ctx = (struct gl_context *) userData; + _mesa_delete_pipeline_object(ctx, obj); +} + + +/** + * Free pipeline state for given context. + */ +void +_mesa_free_pipeline_data(struct gl_context *ctx) +{ + _mesa_HashDeleteAll(ctx->Pipeline.Objects, delete_pipelineobj_cb, ctx); + _mesa_DeleteHashTable(ctx->Pipeline.Objects); +} + +/** + * Look up the pipeline object for the given ID. + * + * \returns + * Either a pointer to the pipeline object with the specified ID or \c NULL for + * a non-existent ID. The spec defines ID 0 as being technically + * non-existent. + */ +static inline struct gl_pipeline_object * +lookup_pipeline_object(struct gl_context *ctx, GLuint id) +{ + if (id == 0) + return NULL; + else + return (struct gl_pipeline_object *) + _mesa_HashLookup(ctx->Pipeline.Objects, id); +} + +/** + * Add the given pipeline object to the pipeline object pool. + */ +static void +save_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) +{ + if (obj->Name > 0) { + _mesa_HashInsert(ctx->Pipeline.Objects, obj->Name, obj); + } +} + +/** + * Remove the given pipeline object from the pipeline object pool. + * Do not deallocate the pipeline object though. + */ +static void +remove_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj) +{ + if (obj->Name > 0) { + _mesa_HashRemove(ctx->Pipeline.Objects, obj->Name); + } +} + +/** + * Set ptr to obj w/ reference counting. + * Note: this should only be called from the _mesa_reference_pipeline_object() + * inline function. + */ +void +_mesa_reference_pipeline_object_(struct gl_context *ctx, + struct gl_pipeline_object **ptr, + struct gl_pipeline_object *obj) +{ + assert(*ptr != obj); + + if (*ptr) { + /* Unreference the old pipeline object */ + GLboolean deleteFlag = GL_FALSE; + struct gl_pipeline_object *oldObj = *ptr; + + mtx_lock(&oldObj->Mutex); + ASSERT(oldObj->RefCount > 0); + oldObj->RefCount--; + deleteFlag = (oldObj->RefCount == 0); + mtx_unlock(&oldObj->Mutex); + + if (deleteFlag) { + _mesa_delete_pipeline_object(ctx, oldObj); + } + + *ptr = NULL; + } + ASSERT(!*ptr); + + if (obj) { + /* reference new pipeline object */ + mtx_lock(&obj->Mutex); + if (obj->RefCount == 0) { + /* this pipeline's being deleted (look just above) */ + /* Not sure this can ever really happen. Warn if it does. */ + _mesa_problem(NULL, "referencing deleted pipeline object"); + *ptr = NULL; + } + else { + obj->RefCount++; + *ptr = obj; + } + mtx_unlock(&obj->Mutex); + } +} + +/** + * Bound program to severals stages of the pipeline + */ +void GLAPIENTRY +_mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) +{ +} + +/** + * Use the named shader program for subsequent glUniform calls (if pipeline + * bound) + */ +void GLAPIENTRY +_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = NULL; + struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + + if (program != 0) { + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glActiveShaderProgram(program)"); + if (shProg == NULL) + return; + } + + if (!pipe) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveShaderProgram(pipeline)"); + return; + } + + /* Object is created by any Pipeline call but glGenProgramPipelines, + * glIsProgramPipeline and GetProgramPipelineInfoLog + */ + pipe->EverBound = GL_TRUE; + + if ((shProg != NULL) && !shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glActiveShaderProgram(program %u not linked)", shProg->Name); + return; + } + + _mesa_reference_shader_program(ctx, &pipe->ActiveProgram, shProg); +} + +/** + * Make program of the pipeline current + */ +void GLAPIENTRY +_mesa_BindProgramPipeline(GLuint pipeline) +{ +} + +/** + * Delete a set of pipeline objects. + * + * \param n Number of pipeline objects to delete. + * \param ids pipeline of \c n pipeline object IDs. + */ +void GLAPIENTRY +_mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + GLsizei i; + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgramPipelines(n<0)"); + return; + } + + for (i = 0; i < n; i++) { + struct gl_pipeline_object *obj = + lookup_pipeline_object(ctx, pipelines[i]); + + if (obj) { + ASSERT(obj->Name == pipelines[i]); + + /* If the pipeline object is currently bound, the spec says "If an + * object that is currently bound is deleted, the binding for that + * object reverts to zero and no program pipeline object becomes + * current." + */ + if (obj == ctx->Pipeline.Current) { + _mesa_BindProgramPipeline(0); + } + + /* The ID is immediately freed for re-use */ + remove_pipeline_object(ctx, obj); + + /* Unreference the pipeline object. + * If refcount hits zero, the object will be deleted. + */ + _mesa_reference_pipeline_object(ctx, &obj, NULL); + } + } +} + +/** + * Generate a set of unique pipeline object IDs and store them in \c pipelines. + * \param n Number of IDs to generate. + * \param pipelines pipeline of \c n locations to store the IDs. + */ +void GLAPIENTRY +_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines) +{ + GET_CURRENT_CONTEXT(ctx); + + GLuint first; + GLint i; + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramPipelines(n<0)"); + return; + } + + if (!pipelines) { + return; + } + + first = _mesa_HashFindFreeKeyBlock(ctx->Pipeline.Objects, n); + + for (i = 0; i < n; i++) { + struct gl_pipeline_object *obj; + GLuint name = first + i; + + obj = _mesa_new_pipeline_object(ctx, name); + if (!obj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramPipelines"); + return; + } + + save_pipeline_object(ctx, obj); + pipelines[i] = first + i; + } + +} + +/** + * Determine if ID is the name of an pipeline object. + * + * \param id ID of the potential pipeline object. + * \return \c GL_TRUE if \c id is the name of a pipeline object, + * \c GL_FALSE otherwise. + */ +GLboolean GLAPIENTRY +_mesa_IsProgramPipeline(GLuint pipeline) +{ + GET_CURRENT_CONTEXT(ctx); + + struct gl_pipeline_object *obj = lookup_pipeline_object(ctx, pipeline); + if (obj == NULL) + return GL_FALSE; + + return obj->EverBound; +} + +/** + * glGetProgramPipelineiv() - get pipeline shader state. + */ +void GLAPIENTRY +_mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_pipeline_object *pipe = lookup_pipeline_object(ctx, pipeline); + + /* Are geometry shaders available in this context? + */ + const bool has_gs = _mesa_has_geometry_shaders(ctx); + + if (!pipe) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramPipelineiv(pipeline)"); + return; + } + + /* Object is created by any Pipeline call but glGenProgramPipelines, + * glIsProgramPipeline and GetProgramPipelineInfoLog + */ + pipe->EverBound = GL_TRUE; + + switch (pname) { + case GL_ACTIVE_PROGRAM: + *params = pipe->ActiveProgram ? pipe->ActiveProgram->Name : 0; + return; + case GL_INFO_LOG_LENGTH: + /* FINISHME: Implement the info log. + */ + *params = 0; + return; + case GL_VALIDATE_STATUS: + /* FINISHME: Implement validation status. + */ + *params = 0; + return; + case GL_VERTEX_SHADER: + *params = pipe->CurrentProgram[MESA_SHADER_VERTEX] + ? pipe->CurrentProgram[MESA_SHADER_VERTEX]->Name : 0; + return; + case GL_TESS_EVALUATION_SHADER: + /* NOT YET SUPPORTED */ + break; + case GL_TESS_CONTROL_SHADER: + /* NOT YET SUPPORTED */ + break; + case GL_GEOMETRY_SHADER: + if (!has_gs) + break; + *params = pipe->CurrentProgram[MESA_SHADER_GEOMETRY] + ? pipe->CurrentProgram[MESA_SHADER_GEOMETRY]->Name : 0; + return; + case GL_FRAGMENT_SHADER: + *params = pipe->CurrentProgram[MESA_SHADER_FRAGMENT] + ? pipe->CurrentProgram[MESA_SHADER_FRAGMENT]->Name : 0; + return; + default: + break; + } + + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramPipelineiv(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); +} + +/** + * Check compatibility of pipeline's program + */ +void GLAPIENTRY +_mesa_ValidateProgramPipeline(GLuint pipeline) +{ +} + +void GLAPIENTRY +_mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ +} diff --git a/mesalib/src/mesa/main/pipelineobj.h b/mesalib/src/mesa/main/pipelineobj.h new file mode 100644 index 000000000..46d5fab42 --- /dev/null +++ b/mesalib/src/mesa/main/pipelineobj.h @@ -0,0 +1,95 @@ +/* + * Mesa 3-D graphics library + * + * Copyright © 2013 Gregory Hainaut + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef PIPELINEOBJ_H +#define PIPELINEOBJ_H + +#include "glheader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _glapi_table; +struct gl_context; +struct gl_pipeline_object; + +extern void +_mesa_delete_pipeline_object(struct gl_context *ctx, struct gl_pipeline_object *obj); + +extern void +_mesa_init_pipeline(struct gl_context *ctx); + +extern void +_mesa_free_pipeline_data(struct gl_context *ctx); + +extern void +_mesa_reference_pipeline_object_(struct gl_context *ctx, + struct gl_pipeline_object **ptr, + struct gl_pipeline_object *obj); + +static inline void +_mesa_reference_pipeline_object(struct gl_context *ctx, + struct gl_pipeline_object **ptr, + struct gl_pipeline_object *obj) +{ + if (*ptr != obj) + _mesa_reference_pipeline_object_(ctx, ptr, obj); +} + + +extern void GLAPIENTRY +_mesa_UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program); + +extern void GLAPIENTRY +_mesa_ActiveShaderProgram(GLuint pipeline, GLuint program); + +extern void GLAPIENTRY +_mesa_BindProgramPipeline(GLuint pipeline); + +extern void GLAPIENTRY +_mesa_DeleteProgramPipelines(GLsizei n, const GLuint *pipelines); + +extern void GLAPIENTRY +_mesa_GenProgramPipelines(GLsizei n, GLuint *pipelines); + +extern GLboolean GLAPIENTRY +_mesa_IsProgramPipeline(GLuint pipeline); + +extern void GLAPIENTRY +_mesa_GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_ValidateProgramPipeline(GLuint pipeline); + +extern void GLAPIENTRY +_mesa_GetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +#ifdef __cplusplus +} +#endif + +#endif /* PIPELINEOBJ_H */ diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index e16346896..b09cf5499 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -595,7 +595,7 @@ fast_read_depth_stencil_pixels(struct gl_context *ctx, return GL_FALSE; if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM && - rb->Format != MESA_FORMAT_Z24_UNORM_X8_UINT) + rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT) return GL_FALSE; ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, @@ -1033,7 +1033,7 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && - _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { + _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); return; diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index 2ff96e548..0bc7f2b96 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -38,7 +38,7 @@ void _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) { - _glthread_INIT_MUTEX(rb->Mutex); + mtx_init(&rb->Mutex, mtx_plain); rb->ClassID = 0; rb->Name = name; @@ -83,7 +83,7 @@ _mesa_new_renderbuffer(struct gl_context *ctx, GLuint name) void _mesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { - _glthread_DESTROY_MUTEX(rb->Mutex); + mtx_destroy(&rb->Mutex); free(rb->Label); free(rb); } @@ -153,12 +153,12 @@ _mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr, GLboolean deleteFlag = GL_FALSE; struct gl_renderbuffer *oldRb = *ptr; - _glthread_LOCK_MUTEX(oldRb->Mutex); + mtx_lock(&oldRb->Mutex); ASSERT(oldRb->RefCount > 0); oldRb->RefCount--; /*printf("RB DECR %p (%d) to %d\n", (void*) oldRb, oldRb->Name, oldRb->RefCount);*/ deleteFlag = (oldRb->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldRb->Mutex); + mtx_unlock(&oldRb->Mutex); if (deleteFlag) { GET_CURRENT_CONTEXT(ctx); @@ -171,10 +171,10 @@ _mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr, if (rb) { /* reference new renderbuffer */ - _glthread_LOCK_MUTEX(rb->Mutex); + mtx_lock(&rb->Mutex); rb->RefCount++; /*printf("RB INCR %p (%d) to %d\n", (void*) rb, rb->Name, rb->RefCount);*/ - _glthread_UNLOCK_MUTEX(rb->Mutex); + mtx_unlock(&rb->Mutex); *ptr = rb; } } diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index 7285ef5ed..4900d5256 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -66,7 +66,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, GLboolean deleteFlag = GL_FALSE; struct gl_sampler_object *oldSamp = *ptr; - /*_glthread_LOCK_MUTEX(oldSamp->Mutex);*/ + /*mtx_lock(&oldSamp->Mutex);*/ ASSERT(oldSamp->RefCount > 0); oldSamp->RefCount--; #if 0 @@ -74,7 +74,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, (void *) oldSamp, oldSamp->Name, oldSamp->RefCount); #endif deleteFlag = (oldSamp->RefCount == 0); - /*_glthread_UNLOCK_MUTEX(oldSamp->Mutex);*/ + /*mtx_unlock(&oldSamp->Mutex);*/ if (deleteFlag) { ASSERT(ctx->Driver.DeleteSamplerObject); @@ -87,7 +87,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, if (samp) { /* reference new sampler */ - /*_glthread_LOCK_MUTEX(samp->Mutex);*/ + /*mtx_lock(&samp->Mutex);*/ if (samp->RefCount == 0) { /* this sampler's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -102,7 +102,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, #endif *ptr = samp; } - /*_glthread_UNLOCK_MUTEX(samp->Mutex);*/ + /*mtx_unlock(&samp->Mutex);*/ } } @@ -203,7 +203,7 @@ _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) return; } - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); for (i = 0; i < count; i++) { if (samplers[i]) { @@ -228,7 +228,7 @@ _mesa_DeleteSamplers(GLsizei count, const GLuint *samplers) } } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 65b6b16bb..5060cbb0b 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -65,8 +65,8 @@ /** * Return mask of GLSL_x flags by examining the MESA_GLSL env var. */ -static GLbitfield -get_shader_flags(void) +GLbitfield +_mesa_get_shader_flags(void) { GLbitfield flags = 0x0; const char *env = _mesa_getenv("MESA_GLSL"); @@ -120,7 +120,11 @@ _mesa_init_shader_state(struct gl_context *ctx) for (sh = 0; sh < MESA_SHADER_STAGES; ++sh) memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options)); - ctx->Shader.Flags = get_shader_flags(); + ctx->Shader.Flags = _mesa_get_shader_flags(); + + /* Extended for ARB_separate_shader_objects */ + ctx->Shader.RefCount = 1; + mtx_init(&ctx->Shader.Mutex, mtx_plain); } @@ -138,6 +142,10 @@ _mesa_free_shader_state(struct gl_context *ctx) _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, NULL); _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); + + /* Extended for ARB_separate_shader_objects */ + assert(ctx->Shader.RefCount == 1); + mtx_destroy(&ctx->Shader.Mutex); } @@ -383,30 +391,31 @@ detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); /* alloc new, smaller array */ - newList = - malloc((n - 1) * sizeof(struct gl_shader *)); + newList = malloc((n - 1) * sizeof(struct gl_shader *)); if (!newList) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); return; } + /* Copy old list entries to new list, skipping removed entry at [i] */ for (j = 0; j < i; j++) { newList[j] = shProg->Shaders[j]; } - while (++i < n) + while (++i < n) { newList[j++] = shProg->Shaders[i]; - free(shProg->Shaders); + } + /* Free old list and install new one */ + free(shProg->Shaders); shProg->Shaders = newList; shProg->NumShaders = n - 1; #ifdef DEBUG - /* sanity check */ - { - for (j = 0; j < shProg->NumShaders; j++) { - assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || - shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); - assert(shProg->Shaders[j]->RefCount > 0); - } + /* sanity check - make sure the new list's entries are sensible */ + for (j = 0; j < shProg->NumShaders; j++) { + assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || + shProg->Shaders[j]->Type == GL_GEOMETRY_SHADER || + shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); + assert(shProg->Shaders[j]->RefCount > 0); } #endif @@ -605,6 +614,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param if (check_gs_query(ctx, shProg)) *params = shProg->Geom.VerticesOut; return; + case GL_GEOMETRY_SHADER_INVOCATIONS: + if (!has_core_gs || !ctx->Extensions.ARB_gpu_shader5) + break; + if (check_gs_query(ctx, shProg)) + *params = shProg->Geom.Invocations; + return; case GL_GEOMETRY_INPUT_TYPE: if (!has_core_gs) break; @@ -681,6 +696,12 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param params[i] = shProg->Comp.LocalSize[i]; return; } + case GL_PROGRAM_SEPARABLE: + if (!ctx->Extensions.ARB_separate_shader_objects) + break; + + *params = shProg->SeparateShader; + return; default: break; } @@ -817,9 +838,10 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) sh->CompileStatus = GL_FALSE; } else { if (ctx->Shader.Flags & GLSL_DUMP) { - printf("GLSL source for %s shader %d:\n", - _mesa_shader_stage_to_string(sh->Stage), sh->Name); - printf("%s\n", sh->Source); + fprintf(stderr, "GLSL source for %s shader %d:\n", + _mesa_shader_stage_to_string(sh->Stage), sh->Name); + fprintf(stderr, "%s\n", sh->Source); + fflush(stderr); } /* this call will set the shader->CompileStatus field to indicate if @@ -833,16 +855,17 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) if (ctx->Shader.Flags & GLSL_DUMP) { if (sh->CompileStatus) { - printf("GLSL IR for shader %d:\n", sh->Name); - _mesa_print_ir(sh->ir, NULL); - printf("\n\n"); + fprintf(stderr, "GLSL IR for shader %d:\n", sh->Name); + _mesa_print_ir(stderr, sh->ir, NULL); + fprintf(stderr, "\n\n"); } else { - printf("GLSL shader %d failed to compile.\n", sh->Name); + fprintf(stderr, "GLSL shader %d failed to compile.\n", sh->Name); } if (sh->InfoLog && sh->InfoLog[0] != 0) { - printf("GLSL shader %d info log:\n", sh->Name); - printf("%s\n", sh->InfoLog); + fprintf(stderr, "GLSL shader %d info log:\n", sh->Name); + fprintf(stderr, "%s\n", sh->InfoLog); } + fflush(stderr); } } @@ -1721,6 +1744,25 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value) */ shProg->BinaryRetreivableHint = value; return; + + case GL_PROGRAM_SEPARABLE: + if (!ctx->Extensions.ARB_separate_shader_objects) + break; + + /* Spec imply that the behavior is the same as ARB_get_program_binary + * Chapter 7.3 Program Objects + */ + if (value != GL_TRUE && value != GL_FALSE) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glProgramParameteri(pname=%s, value=%d): " + "value must be 0 or 1.", + _mesa_lookup_enum_by_nr(pname), + value); + return; + } + shProg->SeparateShader = value; + return; + default: break; } @@ -1792,19 +1834,16 @@ _mesa_ActiveProgramEXT(GLuint program) return; } - -/** - * For GL_EXT_separate_shader_objects - */ -GLuint GLAPIENTRY -_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) +static GLuint +_mesa_create_shader_program(struct gl_context* ctx, GLboolean separate, + GLenum type, GLsizei count, const GLchar* const *strings) { - GET_CURRENT_CONTEXT(ctx); const GLuint shader = create_shader(ctx, type); GLuint program = 0; if (shader) { - shader_source(ctx, shader, _mesa_strdup(string)); + _mesa_ShaderSource(shader, count, strings, NULL); + compile_shader(ctx, shader); program = create_shader_program(ctx); @@ -1816,6 +1855,8 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) shProg = _mesa_lookup_shader_program(ctx, program); sh = _mesa_lookup_shader(ctx, shader); + shProg->SeparateShader = separate; + get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); if (compiled) { attach_shader(ctx, program, shader); @@ -1858,6 +1899,7 @@ _mesa_copy_linked_program_data(gl_shader_stage type, struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst; dst_gp->VerticesIn = src->Geom.VerticesIn; dst_gp->VerticesOut = src->Geom.VerticesOut; + dst_gp->Invocations = src->Geom.Invocations; dst_gp->InputType = src->Geom.InputType; dst_gp->OutputType = src->Geom.OutputType; dst->UsesClipDistanceOut = src->Geom.UsesClipDistance; @@ -1875,3 +1917,30 @@ _mesa_copy_linked_program_data(gl_shader_stage type, break; } } + + +/** + * For GL_EXT_separate_shader_objects + */ +GLuint GLAPIENTRY +_mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) +{ + GET_CURRENT_CONTEXT(ctx); + + return _mesa_create_shader_program(ctx, GL_FALSE, type, 1, &string); +} + +/** + * ARB_separate_shader_objects: Compile & Link Program + * + * Basically the same as _mesa_CreateShaderProgramEXT but with support of + * multiple strings and sets the SeparateShader flag to true. + */ +GLuint GLAPIENTRY +_mesa_CreateShaderProgramv(GLenum type, GLsizei count, + const GLchar* const *strings) +{ + GET_CURRENT_CONTEXT(ctx); + + return _mesa_create_shader_program(ctx, GL_TRUE, type, count, strings); +} diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h index 10f810caf..44426cc65 100644 --- a/mesalib/src/mesa/main/shaderapi.h +++ b/mesalib/src/mesa/main/shaderapi.h @@ -40,6 +40,9 @@ struct _glapi_table; struct gl_context; struct gl_shader_program; +extern GLbitfield +_mesa_get_shader_flags(void); + extern void _mesa_copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src); @@ -219,6 +222,11 @@ extern bool _mesa_validate_shader_target(const struct gl_context *ctx, GLenum type); +/* GL_ARB_separate_shader_objects */ +extern GLuint GLAPIENTRY +_mesa_CreateShaderProgramv(GLenum type, GLsizei count, + const GLchar* const *strings); + #ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index 4f4bb69a8..d5c3d8099 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -355,6 +355,7 @@ _mesa_free_shader_program_data(struct gl_context *ctx, } free(shProg->Label); + shProg->Label = NULL; } diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c index c11c7f9e9..dc22025c2 100644 --- a/mesalib/src/mesa/main/shared.c +++ b/mesalib/src/mesa/main/shared.c @@ -62,7 +62,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx) if (!shared) return NULL; - _glthread_INIT_MUTEX(shared->Mutex); + mtx_init(&shared->Mutex, mtx_plain); shared->DisplayList = _mesa_NewHashTable(); shared->TexObjects = _mesa_NewHashTable(); @@ -113,7 +113,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx) assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); /* Mutex and timestamp for texobj state validation */ - _glthread_INIT_MUTEX(shared->TexMutex); + mtx_init(&shared->TexMutex, mtx_plain); shared->TextureStateStamp = 0; shared->FrameBuffers = _mesa_NewHashTable(); @@ -186,10 +186,8 @@ delete_bufferobj_cb(GLuint id, void *data, void *userData) { struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; struct gl_context *ctx = (struct gl_context *) userData; - if (_mesa_bufferobj_mapped(bufObj)) { - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->Pointer = NULL; - } + + _mesa_buffer_unmap_all_mappings(ctx, bufObj); _mesa_reference_buffer_object(ctx, &bufObj, NULL); } @@ -356,8 +354,8 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); _mesa_DeleteHashTable(shared->TexObjects); - _glthread_DESTROY_MUTEX(shared->Mutex); - _glthread_DESTROY_MUTEX(shared->TexMutex); + mtx_destroy(&shared->Mutex); + mtx_destroy(&shared->TexMutex); free(shared); } @@ -380,11 +378,11 @@ _mesa_reference_shared_state(struct gl_context *ctx, struct gl_shared_state *old = *ptr; GLboolean delete; - _glthread_LOCK_MUTEX(old->Mutex); + mtx_lock(&old->Mutex); assert(old->RefCount >= 1); old->RefCount--; delete = (old->RefCount == 0); - _glthread_UNLOCK_MUTEX(old->Mutex); + mtx_unlock(&old->Mutex); if (delete) { free_shared_state(ctx, old); @@ -395,9 +393,9 @@ _mesa_reference_shared_state(struct gl_context *ctx, if (state) { /* reference new state */ - _glthread_LOCK_MUTEX(state->Mutex); + mtx_lock(&state->Mutex); state->RefCount++; *ptr = state; - _glthread_UNLOCK_MUTEX(state->Mutex); + mtx_unlock(&state->Mutex); } } diff --git a/mesalib/src/mesa/main/syncobj.c b/mesalib/src/mesa/main/syncobj.c index ad21f3b67..a88d7e469 100644 --- a/mesalib/src/mesa/main/syncobj.c +++ b/mesalib/src/mesa/main/syncobj.c @@ -184,9 +184,9 @@ _mesa_validate_sync(struct gl_context *ctx, void _mesa_ref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) { - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); syncObj->RefCount++; - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -195,7 +195,7 @@ _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) { struct set_entry *entry; - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); syncObj->RefCount--; if (syncObj->RefCount == 0) { entry = _mesa_set_search(ctx->Shared->SyncObjects, @@ -203,11 +203,11 @@ _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) syncObj); assert (entry != NULL); _mesa_set_remove(ctx->Shared->SyncObjects, entry); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); ctx->Driver.DeleteSyncObject(ctx, syncObj); } else { - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } } @@ -288,11 +288,11 @@ _mesa_FenceSync(GLenum condition, GLbitfield flags) ctx->Driver.FenceSync(ctx, syncObj, condition, flags); - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_set_add(ctx->Shared->SyncObjects, _mesa_hash_pointer(syncObj), syncObj); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); return (GLsync) syncObj; } diff --git a/mesalib/src/mesa/main/texcompress_etc.c b/mesalib/src/mesa/main/texcompress_etc.c index e3862be45..cbda68940 100644 --- a/mesalib/src/mesa/main/texcompress_etc.c +++ b/mesalib/src/mesa/main/texcompress_etc.c @@ -429,8 +429,7 @@ etc2_rgb8_parse_block(struct etc2_block *block, block->is_planar_mode = true; /* opaque bit must be set in planar mode */ - if (!block->opaque) - block->opaque = true; + block->opaque = true; for (i = 0; i < 3; i++) { block->base_colors[0][i] = etc2_base_color_o_planar(src, i); diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index bda2d8e17..004e7ebac 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -209,13 +209,13 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: RETURN_IF_SUPPORTED(MESA_FORMAT_Z_UNORM32); - RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT); + RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); break; case GL_DEPTH_COMPONENT16: RETURN_IF_SUPPORTED(MESA_FORMAT_Z_UNORM16); - RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT); + RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); break; case GL_COMPRESSED_ALPHA_ARB: @@ -426,7 +426,7 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, case GL_DEPTH_STENCIL_EXT: case GL_DEPTH24_STENCIL8_EXT: RETURN_IF_SUPPORTED(MESA_FORMAT_S8_UINT_Z24_UNORM); - RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_X8_UINT); + RETURN_IF_SUPPORTED(MESA_FORMAT_Z24_UNORM_S8_UINT); break; case GL_DEPTH_COMPONENT32F: diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 133fa5376..daabf2e81 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -130,6 +130,10 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, const GLint depth = texImage->Depth; GLint img, row; + assert(format == GL_DEPTH_STENCIL); + assert(type == GL_UNSIGNED_INT_24_8); + /* XXX type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV is not handled yet */ + for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; @@ -145,8 +149,11 @@ get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, width, height, format, type, img, row, 0); - /* XXX Z24_S8 vs. S8_Z24??? */ - memcpy(dest, src, width * sizeof(GLuint)); + /* Unpack from texture's format to GL's z24_s8 layout */ + _mesa_unpack_uint_24_8_depth_stencil_row(texImage->TexFormat, + width, + (const GLuint *) src, + dest); if (ctx->Pack.SwapBytes) { _mesa_swap4((GLuint *) dest, width); } @@ -635,7 +642,8 @@ _mesa_get_teximage(struct gl_context *ctx, */ GLubyte *buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, - GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); + GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, + MAP_INTERNAL); if (!buf) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); @@ -664,7 +672,7 @@ _mesa_get_teximage(struct gl_context *ctx, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } } @@ -689,7 +697,8 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, /* pack texture image into a PBO */ GLubyte *buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, - GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); + GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, + MAP_INTERNAL); if (!buf) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, @@ -731,7 +740,7 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } } @@ -861,7 +870,7 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* PBO should not be mapped */ - if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(PBO is mapped)"); return GL_TRUE; @@ -1004,7 +1013,7 @@ getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, } /* make sure PBO is not mapped */ - if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { + if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(PBO is mapped)"); return GL_TRUE; diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 4d635fe7f..0519d221f 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -397,11 +397,6 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) if (ctx->Extensions.ARB_texture_rg) { switch (internalFormat) { case GL_R16F: - /* R16F depends on both ARB_half_float_pixel and ARB_texture_float. - */ - if (!ctx->Extensions.ARB_half_float_pixel) - break; - /* FALLTHROUGH */ case GL_R32F: if (!ctx->Extensions.ARB_texture_float) break; @@ -422,11 +417,6 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) return GL_RED; case GL_RG16F: - /* RG16F depends on both ARB_half_float_pixel and ARB_texture_float. - */ - if (!ctx->Extensions.ARB_half_float_pixel) - break; - /* FALLTHROUGH */ case GL_RG32F: if (!ctx->Extensions.ARB_texture_float) break; @@ -2254,9 +2244,10 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, /* This will detect any invalid internalFormat value */ if (!_mesa_is_compressed_format(ctx, internalFormat)) { - reason = "internalFormat"; - error = GL_INVALID_ENUM; - goto error; + _mesa_error(ctx, GL_INVALID_ENUM, + "glCompressedTexImage%dD(internalFormat=%s)", + dimensions, _mesa_lookup_enum_by_nr(internalFormat)); + return GL_TRUE; } switch (internalFormat) { @@ -2348,6 +2339,7 @@ compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, return GL_FALSE; error: + /* Note: not all error paths exit through here. */ _mesa_error(ctx, error, "glCompressedTexImage%dD(%s)", dimensions, reason); return GL_TRUE; } @@ -2563,7 +2555,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, break; default: _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } } @@ -2571,7 +2564,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, baseFormat = _mesa_base_tex_format(ctx, internalFormat); if (baseFormat < 0) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } @@ -2580,7 +2574,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, if (_mesa_is_color_format(internalFormat)) { if (rb_base_format < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } } @@ -2606,7 +2601,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, } if (!valid) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(internalFormat)", dimensions); + "glCopyTexImage%dD(internalFormat=%s)", dimensions, + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } } @@ -4183,10 +4179,18 @@ _mesa_validate_texbuffer_format(const struct gl_context *ctx, return MESA_FORMAT_NONE; datatype = _mesa_get_format_datatype(format); - if (datatype == GL_FLOAT && !ctx->Extensions.ARB_texture_float) - return MESA_FORMAT_NONE; - if (datatype == GL_HALF_FLOAT && !ctx->Extensions.ARB_half_float_pixel) + /* The GL_ARB_texture_buffer_object spec says: + * + * "If ARB_texture_float is not supported, references to the + * floating-point internal formats provided by that extension should be + * removed, and such formats may not be passed to TexBufferARB." + * + * As a result, GL_HALF_FLOAT internal format depends on both + * GL_ARB_texture_float and GL_ARB_half_float_pixel. + */ + if ((datatype == GL_FLOAT || datatype == GL_HALF_FLOAT) && + !ctx->Extensions.ARB_texture_float) return MESA_FORMAT_NONE; if (!ctx->Extensions.ARB_texture_rg) { diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 5f8a47776..51d94d17e 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -163,7 +163,7 @@ _mesa_legal_texture_base_format_for_target(struct gl_context *ctx, static inline void _mesa_lock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) { - _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); + mtx_lock(&ctx->Shared->TexMutex); ctx->Shared->TextureStateStamp++; (void) texObj; } @@ -172,7 +172,7 @@ static inline void _mesa_unlock_texture(struct gl_context *ctx, struct gl_texture_object *texObj) { (void) texObj; - _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); + mtx_unlock(&ctx->Shared->TexMutex); } /*@}*/ diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 6adc0ae84..3375fe36b 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -115,7 +115,7 @@ _mesa_initialize_texture_object( struct gl_context *ctx, memset(obj, 0, sizeof(*obj)); /* init the non-zero fields */ - _glthread_INIT_MUTEX(obj->Mutex); + mtx_init(&obj->Mutex, mtx_plain); obj->RefCount = 1; obj->Name = name; obj->Target = target; @@ -237,7 +237,7 @@ _mesa_delete_texture_object(struct gl_context *ctx, _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL); /* destroy the mutex -- it may have allocated memory (eg on bsd) */ - _glthread_DESTROY_MUTEX(texObj->Mutex); + mtx_destroy(&texObj->Mutex); free(texObj->Label); @@ -374,12 +374,12 @@ _mesa_reference_texobj_(struct gl_texture_object **ptr, ASSERT(valid_texture_object(oldTex)); (void) valid_texture_object; /* silence warning in release builds */ - _glthread_LOCK_MUTEX(oldTex->Mutex); + mtx_lock(&oldTex->Mutex); ASSERT(oldTex->RefCount > 0); oldTex->RefCount--; deleteFlag = (oldTex->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldTex->Mutex); + mtx_unlock(&oldTex->Mutex); if (deleteFlag) { GET_CURRENT_CONTEXT(ctx); @@ -396,7 +396,7 @@ _mesa_reference_texobj_(struct gl_texture_object **ptr, if (tex) { /* reference new texture */ ASSERT(valid_texture_object(tex)); - _glthread_LOCK_MUTEX(tex->Mutex); + mtx_lock(&tex->Mutex); if (tex->RefCount == 0) { /* this texture's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -407,7 +407,7 @@ _mesa_reference_texobj_(struct gl_texture_object **ptr, tex->RefCount++; *ptr = tex; } - _glthread_UNLOCK_MUTEX(tex->Mutex); + mtx_unlock(&tex->Mutex); } } @@ -1009,7 +1009,7 @@ _mesa_GenTextures( GLsizei n, GLuint *textures ) /* * This must be atomic (generation and allocation of texture IDs) */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); @@ -1020,7 +1020,7 @@ _mesa_GenTextures( GLsizei n, GLuint *textures ) GLenum target = 0; texObj = ctx->Driver.NewTextureObject(ctx, name, target); if (!texObj) { - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures"); return; } @@ -1031,7 +1031,7 @@ _mesa_GenTextures( GLsizei n, GLuint *textures ) textures[i] = name; } - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } @@ -1178,9 +1178,9 @@ _mesa_DeleteTextures( GLsizei n, const GLuint *textures) /* The texture _name_ is now free for re-use. * Remove it from the hash table now. */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); /* Unreference the texobj. If refcount hits zero, the texture * will be deleted. @@ -1313,9 +1313,9 @@ _mesa_BindTexture( GLenum target, GLuint texName ) } /* and insert it into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); } newTexObj->Target = target; } @@ -1327,10 +1327,10 @@ _mesa_BindTexture( GLenum target, GLuint texName ) */ { GLboolean early_out; - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + mtx_lock(&ctx->Shared->Mutex); early_out = ((ctx->Shared->RefCount == 1) && (newTexObj == texUnit->CurrentTex[targetIndex])); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + mtx_unlock(&ctx->Shared->Mutex); if (early_out) { return; } @@ -1493,7 +1493,7 @@ _mesa_IsTexture( GLuint texture ) void _mesa_lock_context_textures( struct gl_context *ctx ) { - _glthread_LOCK_MUTEX(ctx->Shared->TexMutex); + mtx_lock(&ctx->Shared->TexMutex); if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) { ctx->NewState |= _NEW_TEXTURE; @@ -1506,7 +1506,7 @@ void _mesa_unlock_context_textures( struct gl_context *ctx ) { assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp); - _glthread_UNLOCK_MUTEX(ctx->Shared->TexMutex); + mtx_unlock(&ctx->Shared->TexMutex); } void GLAPIENTRY diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index b7ed50dd5..bbdbc2763 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -986,6 +986,9 @@ legal_get_tex_level_parameter_target(struct gl_context *ctx, GLenum target) case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: case GL_PROXY_TEXTURE_CUBE_MAP_ARB: return ctx->Extensions.ARB_texture_cube_map; + case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: + case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB: + return ctx->Extensions.ARB_texture_cube_map_array; case GL_TEXTURE_RECTANGLE_NV: case GL_PROXY_TEXTURE_RECTANGLE_NV: return ctx->Extensions.NV_texture_rectangle; diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 1e4308a04..3e22a0b46 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -1049,7 +1049,7 @@ _mesa_texstore_x8_z24(TEXSTORE_PARAMS) const GLuint depthScale = 0xffffff; (void) dims; - ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); + ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_X8_UINT); { /* general path */ @@ -2558,7 +2558,7 @@ _mesa_texstore_s8_z24(TEXSTORE_PARAMS) GLuint *depth; GLubyte *stencil; - ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_X8_UINT); + ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT || srcFormat == GL_STENCIL_INDEX); @@ -3699,9 +3699,9 @@ _mesa_get_texstore_func(mesa_format format) table[MESA_FORMAT_G16R16_UNORM] = _mesa_texstore_unorm1616; table[MESA_FORMAT_B10G10R10A2_UNORM] = _mesa_texstore_argb2101010; table[MESA_FORMAT_S8_UINT_Z24_UNORM] = _mesa_texstore_z24_s8; - table[MESA_FORMAT_Z24_UNORM_X8_UINT] = _mesa_texstore_s8_z24; + table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_s8_z24; table[MESA_FORMAT_Z_UNORM16] = _mesa_texstore_z16; - table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_x8_z24; + table[MESA_FORMAT_Z24_UNORM_X8_UINT] = _mesa_texstore_x8_z24; table[MESA_FORMAT_X8Z24_UNORM] = _mesa_texstore_z24_x8; table[MESA_FORMAT_Z_UNORM32] = _mesa_texstore_z32; table[MESA_FORMAT_S_UINT8] = _mesa_texstore_s8; diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index 82d7628e8..8cc5da752 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -684,6 +684,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, match = true; break; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: match = (basicType == GLSL_TYPE_INT); break; default: @@ -735,6 +736,22 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, } } + if (uni->type->is_image()) { + int i; + + for (i = 0; i < count; i++) { + const int unit = ((GLint *) values)[i]; + + /* check that the image unit is legal */ + if (unit < 0 || unit >= (int)ctx->Const.MaxImageUnits) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glUniform1i(invalid image unit index for uniform %d)", + location); + return; + } + } + } + /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says: * * "When loading N elements starting at an arbitrary position k in a @@ -830,6 +847,25 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, } } } + + /* If the uniform is an image, update the mapping from image + * uniforms to image units present in the shader data structure. + */ + if (uni->type->is_image()) { + int i, j; + + for (i = 0; i < MESA_SHADER_STAGES; i++) { + if (uni->image[i].active) { + struct gl_shader *sh = shProg->_LinkedShaders[i]; + + for (j = 0; j < count; j++) + sh->ImageUnits[uni->image[i].index + offset + j] = + ((GLint *) values)[j]; + } + } + + ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; + } } /** diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 071d668f3..c25c2df7e 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -270,6 +270,197 @@ _mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value) _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4); } +/** Same as above with direct state access **/ +void GLAPIENTRY +_mesa_ProgramUniform1f(GLuint program, GLint location, GLfloat v0) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1f"); + _mesa_uniform(ctx, shProg, location, 1, &v0, GL_FLOAT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[2]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform2f"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_FLOAT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, + GLfloat v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[3]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform3f"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_FLOAT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, + GLfloat v2, GLfloat v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[4]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4f"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_FLOAT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1i(GLuint program, GLint location, GLint v0) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1i"); + _mesa_uniform(ctx, shProg, location, 1, &v0, GL_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[2]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform2i"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, + GLint v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[3]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform3i"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, + GLint v2, GLint v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[4]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4i"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_INT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4fv(GLuint program, GLint location, GLsizei count, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform4fv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_FLOAT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4iv(GLuint program, GLint location, GLsizei count, + const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform4iv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_INT_VEC4); +} + /** OpenGL 3.0 GLuint-valued functions **/ void GLAPIENTRY @@ -369,6 +560,140 @@ _mesa_UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, 4, 4, location, count, transpose, value); } +/** Same as above with direct state access **/ + +void GLAPIENTRY +_mesa_ProgramUniform1ui(GLuint program, GLint location, GLuint v0) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1ui"); + _mesa_uniform(ctx, shProg, location, 1, &v0, GL_UNSIGNED_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint v[2]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2ui"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_UNSIGNED_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint v[3]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + shProg = _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3ui"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_UNSIGNED_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2, GLuint v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint v[4]; + struct gl_shader_program *shProg; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + shProg = _mesa_lookup_shader_program_err(ctx, program, "glProgramUniform4ui"); + _mesa_uniform(ctx, shProg, location, 1, v, GL_UNSIGNED_INT_VEC4); +} + +void GLAPIENTRY +_mesa_ProgramUniform1uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform1uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT); +} + +void GLAPIENTRY +_mesa_ProgramUniform2uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform2uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT_VEC2); +} + +void GLAPIENTRY +_mesa_ProgramUniform3uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform3uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT_VEC3); +} + +void GLAPIENTRY +_mesa_ProgramUniform4uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniform4uiv"); + _mesa_uniform(ctx, shProg, location, count, value, GL_UNSIGNED_INT_VEC4); +} + + + +void GLAPIENTRY +_mesa_ProgramUniformMatrix2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix2fv"); + _mesa_uniform_matrix(ctx, shProg, 2, 2, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix3fv"); + _mesa_uniform_matrix(ctx, shProg, 3, 3, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix4fv"); + _mesa_uniform_matrix(ctx, shProg, 4, 4, location, count, transpose, value); +} + /** * Non-square UniformMatrix are OpenGL 2.1 @@ -427,6 +752,74 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, 4, 3, location, count, transpose, value); } +/** Same as above with direct state access **/ + +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix2x3fv"); + _mesa_uniform_matrix(ctx, shProg, 2, 3, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix3x2fv"); + _mesa_uniform_matrix(ctx, shProg, 3, 2, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix2x4fv"); + _mesa_uniform_matrix(ctx, shProg, 2, 4, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix4x2fv"); + _mesa_uniform_matrix(ctx, shProg, 4, 2, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix3x4fv"); + _mesa_uniform_matrix(ctx, shProg, 3, 4, location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glProgramUniformMatrix4x3fv"); + _mesa_uniform_matrix(ctx, shProg, 4, 3, location, count, transpose, value); +} + void GLAPIENTRY _mesa_GetnUniformfvARB(GLhandleARB program, GLint location, diff --git a/mesalib/src/mesa/main/uniforms.h b/mesalib/src/mesa/main/uniforms.h index f7cac6328..bd50fd9b8 100644 --- a/mesalib/src/mesa/main/uniforms.h +++ b/mesalib/src/mesa/main/uniforms.h @@ -111,6 +111,89 @@ _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, void GLAPIENTRY _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + +void GLAPIENTRY +_mesa_ProgramUniform1f(GLuint program, GLint, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform2f(GLuint program, GLint, GLfloat, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform3f(GLuint program, GLint, GLfloat, GLfloat, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform4f(GLuint program, GLint, GLfloat, GLfloat, GLfloat, GLfloat); +void GLAPIENTRY +_mesa_ProgramUniform1i(GLuint program, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform2i(GLuint program, GLint, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform3i(GLuint program, GLint, GLint, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform4i(GLuint program, GLint, GLint, GLint, GLint, GLint); +void GLAPIENTRY +_mesa_ProgramUniform1fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform2fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform3fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform4fv(GLuint program, GLint, GLsizei, const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniform1iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform2iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform3iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform4iv(GLuint program, GLint, GLsizei, const GLint *); +void GLAPIENTRY +_mesa_ProgramUniform1ui(GLuint program, GLint location, GLuint v0); +void GLAPIENTRY +_mesa_ProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1); +void GLAPIENTRY +_mesa_ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2); +void GLAPIENTRY +_mesa_ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, + GLuint v2, GLuint v3); +void GLAPIENTRY +_mesa_ProgramUniform1uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniform2uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniform3uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniform4uiv(GLuint program, GLint location, GLsizei count, + const GLuint *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix2fv(GLuint program, GLint, GLsizei, GLboolean, + const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniformMatrix3fv(GLuint program, GLint, GLsizei, GLboolean, + const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniformMatrix4fv(GLuint program, GLint, GLsizei, GLboolean, + const GLfloat *); +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); +void GLAPIENTRY +_mesa_ProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); + void GLAPIENTRY _mesa_GetnUniformfvARB(GLhandleARB, GLint, GLsizei, GLfloat *); void GLAPIENTRY diff --git a/mesalib/src/mesa/main/vdpau.c b/mesalib/src/mesa/main/vdpau.c index 359757607..c2cf20664 100644 --- a/mesalib/src/mesa/main/vdpau.c +++ b/mesalib/src/mesa/main/vdpau.c @@ -205,7 +205,7 @@ _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, numTextureNames, textureNames); } -void GLAPIENTRY +GLboolean GLAPIENTRY _mesa_VDPAUIsSurfaceNV(GLintptr surface) { struct vdp_surface *surf = (struct vdp_surface *)surface; @@ -213,13 +213,14 @@ _mesa_VDPAUIsSurfaceNV(GLintptr surface) if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV"); - return; + return false; } if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) { - _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUIsSurfaceNV"); - return; + return false; } + + return true; } void GLAPIENTRY diff --git a/mesalib/src/mesa/main/vdpau.h b/mesalib/src/mesa/main/vdpau.h index f32d6dacb..627609c50 100644 --- a/mesalib/src/mesa/main/vdpau.h +++ b/mesalib/src/mesa/main/vdpau.h @@ -50,7 +50,7 @@ _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); -extern void GLAPIENTRY +extern GLboolean GLAPIENTRY _mesa_VDPAUIsSurfaceNV(GLintptr surface); extern void GLAPIENTRY diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 9af5f091e..1c0bedf4b 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -232,7 +232,6 @@ compute_version(struct gl_context *ctx) (ctx->API == API_OPENGL_CORE || ctx->Extensions.ARB_color_buffer_float) && ctx->Extensions.ARB_depth_buffer_float && - ctx->Extensions.ARB_half_float_pixel && ctx->Extensions.ARB_half_float_vertex && ctx->Extensions.ARB_map_buffer_range && ctx->Extensions.ARB_shader_texture_lod && diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 74c512b33..9919874a6 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -618,6 +618,7 @@ type_size(const struct glsl_type *type) } return size; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: /* Samplers take up one slot in UNIFORMS[], but they're baked in * at link time. */ @@ -2559,6 +2560,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx, columns = 1; break; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: format = uniform_native; columns = 1; break; @@ -2916,16 +2918,17 @@ get_mesa_program(struct gl_context *ctx, set_branchtargets(&v, mesa_instructions, num_instructions); if (ctx->Shader.Flags & GLSL_DUMP) { - printf("\n"); - printf("GLSL IR for linked %s program %d:\n", target_string, - shader_program->Name); - _mesa_print_ir(shader->ir, NULL); - printf("\n"); - printf("\n"); - printf("Mesa IR for linked %s program %d:\n", target_string, - shader_program->Name); + fprintf(stderr, "\n"); + fprintf(stderr, "GLSL IR for linked %s program %d:\n", target_string, + shader_program->Name); + _mesa_print_ir(stderr, shader->ir, NULL); + fprintf(stderr, "\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Mesa IR for linked %s program %d:\n", target_string, + shader_program->Name); print_program(mesa_instructions, mesa_instruction_annotation, num_instructions); + fflush(stderr); } prog->Instructions = mesa_instructions; @@ -3095,12 +3098,12 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) if (ctx->Shader.Flags & GLSL_DUMP) { if (!prog->LinkStatus) { - printf("GLSL shader program %d failed to link\n", prog->Name); + fprintf(stderr, "GLSL shader program %d failed to link\n", prog->Name); } if (prog->InfoLog && prog->InfoLog[0] != 0) { - printf("GLSL shader program %d info log:\n", prog->Name); - printf("%s\n", prog->InfoLog); + fprintf(stderr, "GLSL shader program %d info log:\n", prog->Name); + fprintf(stderr, "%s\n", prog->InfoLog); } } } diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index fa80bc58c..b7332fccf 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -424,7 +424,7 @@ _mesa_reference_program_(struct gl_context *ctx, if (*ptr) { GLboolean deleteFlag; - /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/ + /*mtx_lock(&(*ptr)->Mutex);*/ #if 0 printf("Program %p ID=%u Target=%s Refcount-- to %d\n", *ptr, (*ptr)->Id, @@ -436,7 +436,7 @@ _mesa_reference_program_(struct gl_context *ctx, (*ptr)->RefCount--; deleteFlag = ((*ptr)->RefCount == 0); - /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/ + /*mtx_lock(&(*ptr)->Mutex);*/ if (deleteFlag) { ASSERT(ctx); @@ -448,7 +448,7 @@ _mesa_reference_program_(struct gl_context *ctx, assert(!*ptr); if (prog) { - /*_glthread_LOCK_MUTEX(prog->Mutex);*/ + /*mtx_lock(&prog->Mutex);*/ prog->RefCount++; #if 0 printf("Program %p ID=%u Target=%s Refcount++ to %d\n", @@ -457,7 +457,7 @@ _mesa_reference_program_(struct gl_context *ctx, (prog->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")), prog->RefCount); #endif - /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/ + /*mtx_unlock(&prog->Mutex);*/ } *ptr = prog; @@ -550,6 +550,7 @@ _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog) struct gl_geometry_program *gpc = gl_geometry_program(clone); gpc->VerticesOut = gp->VerticesOut; gpc->InputType = gp->InputType; + gpc->Invocations = gp->Invocations; gpc->OutputType = gp->OutputType; } break; diff --git a/mesalib/src/mesa/state_tracker/st_atom_scissor.c b/mesalib/src/mesa/state_tracker/st_atom_scissor.c index a1f72da47..a19ade1fa 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_scissor.c +++ b/mesalib/src/mesa/state_tracker/st_atom_scissor.c @@ -43,51 +43,56 @@ static void update_scissor( struct st_context *st ) { - struct pipe_scissor_state scissor; + struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS]; const struct gl_context *ctx = st->ctx; const struct gl_framebuffer *fb = ctx->DrawBuffer; GLint miny, maxy; + int i; + bool changed = false; + for (i = 0 ; i < ctx->Const.MaxViewports; i++) { + scissor[i].minx = 0; + scissor[i].miny = 0; + scissor[i].maxx = fb->Width; + scissor[i].maxy = fb->Height; - scissor.minx = 0; - scissor.miny = 0; - scissor.maxx = fb->Width; - scissor.maxy = fb->Height; + if (ctx->Scissor.EnableFlags & (1 << i)) { + /* need to be careful here with xmax or ymax < 0 */ + GLint xmax = MAX2(0, ctx->Scissor.ScissorArray[i].X + ctx->Scissor.ScissorArray[i].Width); + GLint ymax = MAX2(0, ctx->Scissor.ScissorArray[i].Y + ctx->Scissor.ScissorArray[i].Height); - if (ctx->Scissor.EnableFlags & 1) { - /* need to be careful here with xmax or ymax < 0 */ - GLint xmax = MAX2(0, ctx->Scissor.ScissorArray[0].X + ctx->Scissor.ScissorArray[0].Width); - GLint ymax = MAX2(0, ctx->Scissor.ScissorArray[0].Y + ctx->Scissor.ScissorArray[0].Height); + if (ctx->Scissor.ScissorArray[i].X > (GLint)scissor[i].minx) + scissor[i].minx = ctx->Scissor.ScissorArray[i].X; + if (ctx->Scissor.ScissorArray[i].Y > (GLint)scissor[i].miny) + scissor[i].miny = ctx->Scissor.ScissorArray[i].Y; - if (ctx->Scissor.ScissorArray[0].X > (GLint)scissor.minx) - scissor.minx = ctx->Scissor.ScissorArray[0].X; - if (ctx->Scissor.ScissorArray[0].Y > (GLint)scissor.miny) - scissor.miny = ctx->Scissor.ScissorArray[0].Y; + if (xmax < (GLint) scissor[i].maxx) + scissor[i].maxx = xmax; + if (ymax < (GLint) scissor[i].maxy) + scissor[i].maxy = ymax; + + /* check for null space */ + if (scissor[i].minx >= scissor[i].maxx || scissor[i].miny >= scissor[i].maxy) + scissor[i].minx = scissor[i].miny = scissor[i].maxx = scissor[i].maxy = 0; + } - if (xmax < (GLint) scissor.maxx) - scissor.maxx = xmax; - if (ymax < (GLint) scissor.maxy) - scissor.maxy = ymax; + /* Now invert Y if needed. + * Gallium drivers use the convention Y=0=top for surfaces. + */ + if (st_fb_orientation(fb) == Y_0_TOP) { + miny = fb->Height - scissor[i].maxy; + maxy = fb->Height - scissor[i].miny; + scissor[i].miny = miny; + scissor[i].maxy = maxy; + } - /* check for null space */ - if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy) - scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0; - } - - /* Now invert Y if needed. - * Gallium drivers use the convention Y=0=top for surfaces. - */ - if (st_fb_orientation(fb) == Y_0_TOP) { - miny = fb->Height - scissor.maxy; - maxy = fb->Height - scissor.miny; - scissor.miny = miny; - scissor.maxy = maxy; - } - - if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) { - /* state has changed */ - st->state.scissor = scissor; /* struct copy */ - st->pipe->set_scissor_states(st->pipe, 0, 1, &scissor); /* activate */ + if (memcmp(&scissor[i], &st->state.scissor[i], sizeof(scissor)) != 0) { + /* state has changed */ + st->state.scissor[i] = scissor[i]; /* struct copy */ + changed = true; + } } + if (changed) + st->pipe->set_scissor_states(st->pipe, 0, ctx->Const.MaxViewports, scissor); /* activate */ } diff --git a/mesalib/src/mesa/state_tracker/st_atom_viewport.c b/mesalib/src/mesa/state_tracker/st_atom_viewport.c index 8c6d679a0..7584f9b3d 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_viewport.c +++ b/mesalib/src/mesa/state_tracker/st_atom_viewport.c @@ -43,7 +43,7 @@ update_viewport( struct st_context *st ) { struct gl_context *ctx = st->ctx; GLfloat yScale, yBias; - + int i; /* _NEW_BUFFERS */ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { @@ -61,26 +61,29 @@ update_viewport( struct st_context *st ) /* _NEW_VIEWPORT */ + for (i = 0; i < ctx->Const.MaxViewports; i++) { - GLfloat x = ctx->ViewportArray[0].X; - GLfloat y = ctx->ViewportArray[0].Y; - GLfloat z = ctx->ViewportArray[0].Near; - GLfloat half_width = ctx->ViewportArray[0].Width * 0.5f; - GLfloat half_height = ctx->ViewportArray[0].Height * 0.5f; - GLfloat half_depth = (GLfloat)(ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near) * 0.5f; + GLfloat x = ctx->ViewportArray[i].X; + GLfloat y = ctx->ViewportArray[i].Y; + GLfloat z = ctx->ViewportArray[i].Near; + GLfloat half_width = ctx->ViewportArray[i].Width * 0.5f; + GLfloat half_height = ctx->ViewportArray[i].Height * 0.5f; + GLfloat half_depth = (GLfloat)(ctx->ViewportArray[i].Far - ctx->ViewportArray[i].Near) * 0.5f; - st->state.viewport.scale[0] = half_width; - st->state.viewport.scale[1] = half_height * yScale; - st->state.viewport.scale[2] = half_depth; - st->state.viewport.scale[3] = 1.0; - - st->state.viewport.translate[0] = half_width + x; - st->state.viewport.translate[1] = (half_height + y) * yScale + yBias; - st->state.viewport.translate[2] = half_depth + z; - st->state.viewport.translate[3] = 0.0; + st->state.viewport[i].scale[0] = half_width; + st->state.viewport[i].scale[1] = half_height * yScale; + st->state.viewport[i].scale[2] = half_depth; + st->state.viewport[i].scale[3] = 1.0; - cso_set_viewport(st->cso_context, &st->state.viewport); + st->state.viewport[i].translate[0] = half_width + x; + st->state.viewport[i].translate[1] = (half_height + y) * yScale + yBias; + st->state.viewport[i].translate[2] = half_depth + z; + st->state.viewport[i].translate[3] = 0.0; } + + cso_set_viewport(st->cso_context, &st->state.viewport[0]); + if (ctx->Const.MaxViewports > 1) + st->pipe->set_viewport_states(st->pipe, 1, ctx->Const.MaxViewports - 1, &st->state.viewport[1]); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index c8f088dc8..49c4b903e 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -76,7 +76,7 @@ st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj) struct st_buffer_object *st_obj = st_buffer_object(obj); assert(obj->RefCount == 0); - assert(st_obj->transfer == NULL); + _mesa_buffer_unmap_all_mappings(ctx, obj); if (st_obj->buffer) pipe_resource_reference(&st_obj->buffer, NULL); @@ -176,15 +176,18 @@ st_bufferobj_data(struct gl_context *ctx, GLsizeiptrARB size, const GLvoid * data, GLenum usage, + GLbitfield storageFlags, struct gl_buffer_object *obj) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - unsigned bind, pipe_usage; + unsigned bind, pipe_usage, pipe_flags = 0; if (size && data && st_obj->buffer && - st_obj->Base.Size == size && st_obj->Base.Usage == usage) { + st_obj->Base.Size == size && + st_obj->Base.Usage == usage && + st_obj->Base.StorageFlags == storageFlags) { /* Just discard the old contents and write new data. * This should be the same as creating a new buffer, but we avoid * a lot of validation in Mesa. @@ -200,6 +203,7 @@ st_bufferobj_data(struct gl_context *ctx, st_obj->Base.Size = size; st_obj->Base.Usage = usage; + st_obj->Base.StorageFlags = storageFlags; switch (target) { case GL_PIXEL_PACK_BUFFER_ARB: @@ -225,24 +229,41 @@ st_bufferobj_data(struct gl_context *ctx, bind = 0; } - switch (usage) { - case GL_STATIC_DRAW: - case GL_STATIC_READ: - case GL_STATIC_COPY: - default: - pipe_usage = PIPE_USAGE_DEFAULT; - break; - case GL_DYNAMIC_DRAW: - case GL_DYNAMIC_READ: - case GL_DYNAMIC_COPY: - pipe_usage = PIPE_USAGE_DYNAMIC; - break; - case GL_STREAM_DRAW: - case GL_STREAM_READ: - case GL_STREAM_COPY: - pipe_usage = PIPE_USAGE_STREAM; - break; + /* Set usage. */ + if (st_obj->Base.Immutable) { + /* BufferStorage */ + if (storageFlags & GL_CLIENT_STORAGE_BIT) + pipe_usage = PIPE_USAGE_STAGING; + else + pipe_usage = PIPE_USAGE_DEFAULT; } + else { + /* BufferData */ + switch (usage) { + case GL_STATIC_DRAW: + case GL_STATIC_READ: + case GL_STATIC_COPY: + default: + pipe_usage = PIPE_USAGE_DEFAULT; + break; + case GL_DYNAMIC_DRAW: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + pipe_usage = PIPE_USAGE_DYNAMIC; + break; + case GL_STREAM_DRAW: + case GL_STREAM_READ: + case GL_STREAM_COPY: + pipe_usage = PIPE_USAGE_STREAM; + break; + } + } + + /* Set flags. */ + if (storageFlags & GL_MAP_PERSISTENT_BIT) + pipe_flags |= PIPE_RESOURCE_FLAG_MAP_PERSISTENT; + if (storageFlags & GL_MAP_COHERENT_BIT) + pipe_flags |= PIPE_RESOURCE_FLAG_MAP_COHERENT; pipe_resource_reference( &st_obj->buffer, NULL ); @@ -251,8 +272,20 @@ st_bufferobj_data(struct gl_context *ctx, } if (size != 0) { - st_obj->buffer = pipe_buffer_create(pipe->screen, bind, - pipe_usage, size); + struct pipe_resource buffer; + + memset(&buffer, 0, sizeof buffer); + buffer.target = PIPE_BUFFER; + buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ + buffer.bind = bind; + buffer.usage = pipe_usage; + buffer.flags = pipe_flags; + buffer.width0 = size; + buffer.height0 = 1; + buffer.depth0 = 1; + buffer.array_size = 1; + + st_obj->buffer = pipe->screen->resource_create(pipe->screen, &buffer); if (!st_obj->buffer) { /* out of memory */ @@ -277,7 +310,8 @@ st_bufferobj_data(struct gl_context *ctx, static void * st_bufferobj_map_range(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *obj) + struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); @@ -305,6 +339,12 @@ st_bufferobj_map_range(struct gl_context *ctx, if (access & GL_MAP_UNSYNCHRONIZED_BIT) flags |= PIPE_TRANSFER_UNSYNCHRONIZED; + if (access & GL_MAP_PERSISTENT_BIT) + flags |= PIPE_TRANSFER_PERSISTENT; + + if (access & GL_MAP_COHERENT_BIT) + flags |= PIPE_TRANSFER_COHERENT; + /* ... other flags ... */ @@ -316,28 +356,29 @@ st_bufferobj_map_range(struct gl_context *ctx, assert(offset < obj->Size); assert(offset + length <= obj->Size); - obj->Pointer = pipe_buffer_map_range(pipe, + obj->Mappings[index].Pointer = pipe_buffer_map_range(pipe, st_obj->buffer, offset, length, flags, - &st_obj->transfer); - if (obj->Pointer) { - obj->Offset = offset; - obj->Length = length; - obj->AccessFlags = access; + &st_obj->transfer[index]); + if (obj->Mappings[index].Pointer) { + obj->Mappings[index].Offset = offset; + obj->Mappings[index].Length = length; + obj->Mappings[index].AccessFlags = access; } else { - st_obj->transfer = NULL; + st_obj->transfer[index] = NULL; } - return obj->Pointer; + return obj->Mappings[index].Pointer; } static void st_bufferobj_flush_mapped_range(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj) + struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); @@ -345,14 +386,15 @@ st_bufferobj_flush_mapped_range(struct gl_context *ctx, /* Subrange is relative to mapped range */ assert(offset >= 0); assert(length >= 0); - assert(offset + length <= obj->Length); - assert(obj->Pointer); + assert(offset + length <= obj->Mappings[index].Length); + assert(obj->Mappings[index].Pointer); if (!length) return; - pipe_buffer_flush_mapped_range(pipe, st_obj->transfer, - obj->Offset + offset, length); + pipe_buffer_flush_mapped_range(pipe, st_obj->transfer[index], + obj->Mappings[index].Offset + offset, + length); } @@ -360,18 +402,19 @@ st_bufferobj_flush_mapped_range(struct gl_context *ctx, * Called via glUnmapBufferARB(). */ static GLboolean -st_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj) +st_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - if (obj->Length) - pipe_buffer_unmap(pipe, st_obj->transfer); + if (obj->Mappings[index].Length) + pipe_buffer_unmap(pipe, st_obj->transfer[index]); - st_obj->transfer = NULL; - obj->Pointer = NULL; - obj->Offset = 0; - obj->Length = 0; + st_obj->transfer[index] = NULL; + obj->Mappings[index].Pointer = NULL; + obj->Mappings[index].Offset = 0; + obj->Mappings[index].Length = 0; return GL_TRUE; } @@ -395,8 +438,8 @@ st_copy_buffer_subdata(struct gl_context *ctx, return; /* buffer should not already be mapped */ - assert(!src->Pointer); - assert(!dst->Pointer); + assert(!_mesa_check_disallowed_mapping(src)); + assert(!_mesa_check_disallowed_mapping(dst)); u_box_1d(readOffset, size, &box); diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h index a039c0a50..a5ab12219 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.h @@ -43,7 +43,7 @@ struct st_buffer_object { struct gl_buffer_object Base; struct pipe_resource *buffer; /* GPU storage */ - struct pipe_transfer *transfer; /* In-progress map information */ + struct pipe_transfer *transfer[MAP_COUNT]; }; diff --git a/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c b/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c index 2f1a22b58..dd4dde74c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texturebarrier.c @@ -54,7 +54,24 @@ st_TextureBarrier(struct gl_context *ctx) } +/** + * Called via ctx->Driver.MemoryBarrier() + */ +static void +st_MemoryBarrier(struct gl_context *ctx, GLbitfield barriers) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + unsigned flags = 0; + + if (barriers & GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT) + flags |= PIPE_BARRIER_MAPPED_BUFFER; + + if (flags && pipe->memory_barrier) + pipe->memory_barrier(pipe, flags); +} + void st_init_texture_barrier_functions(struct dd_function_table *functions) { functions->TextureBarrier = st_TextureBarrier; + functions->MemoryBarrier = st_MemoryBarrier; } diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 996e0c6bc..9c699a015 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -115,8 +115,8 @@ struct st_context unsigned size; } constants[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; - struct pipe_scissor_state scissor; - struct pipe_viewport_state viewport; + struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS]; + struct pipe_viewport_state viewport[PIPE_MAX_VIEWPORTS]; unsigned sample_mask; GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */ diff --git a/mesalib/src/mesa/state_tracker/st_draw_feedback.c b/mesalib/src/mesa/state_tracker/st_draw_feedback.c index 09cd9511d..177f6b5ae 100644 --- a/mesalib/src/mesa/state_tracker/st_draw_feedback.c +++ b/mesalib/src/mesa/state_tracker/st_draw_feedback.c @@ -156,7 +156,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, * code sends state updates to the pipe, not to our private draw module. */ assert(draw); - draw_set_viewport_states(draw, 0, 1, &st->state.viewport); + draw_set_viewport_states(draw, 0, 1, &st->state.viewport[0]); draw_set_clip_state(draw, &st->state.clip); draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL); draw_bind_vertex_shader(draw, st->vp_variant->draw_shader); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 9829eb596..18ddd4e47 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -39,6 +39,12 @@ #include "st_extensions.h" #include "st_format.h" + +/* + * Note: we use these function rather than the MIN2, MAX2, CLAMP macros to + * avoid evaluating arguments (which are often function calls) more than once. + */ + static unsigned _min(unsigned a, unsigned b) { return (a < b) ? a : b; @@ -262,10 +268,13 @@ void st_init_limits(struct st_context *st) c->Program[MESA_SHADER_VERTEX].MaxOutputComponents = c->MaxVarying * 4; c->Program[MESA_SHADER_GEOMETRY].MaxInputComponents = c->MaxVarying * 4; c->Program[MESA_SHADER_GEOMETRY].MaxOutputComponents = c->MaxVarying * 4; + c->MaxGeometryOutputVertices = screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES); + c->MaxGeometryTotalOutputComponents = screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS); c->MinProgramTexelOffset = screen->get_param(screen, PIPE_CAP_MIN_TEXEL_OFFSET); c->MaxProgramTexelOffset = screen->get_param(screen, PIPE_CAP_MAX_TEXEL_OFFSET); + c->MaxProgramTextureGatherComponents = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS); c->UniformBooleanTrue = ~0; c->MaxTransformFeedbackBuffers = @@ -373,6 +382,7 @@ void st_init_extensions(struct st_context *st) static const struct st_extension_cap_mapping cap_mapping[] = { { o(ARB_base_instance), PIPE_CAP_START_INSTANCE }, + { o(ARB_buffer_storage), PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT }, { o(ARB_depth_clamp), PIPE_CAP_DEPTH_CLIP_DISABLE }, { o(ARB_depth_texture), PIPE_CAP_TEXTURE_SHADOW_MAP }, { o(ARB_draw_buffers_blend), PIPE_CAP_INDEP_BLEND_FUNC }, @@ -526,7 +536,6 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; ctx->Extensions.ARB_fragment_program = GL_TRUE; ctx->Extensions.ARB_fragment_shader = GL_TRUE; - ctx->Extensions.ARB_half_float_pixel = GL_TRUE; ctx->Extensions.ARB_half_float_vertex = GL_TRUE; ctx->Extensions.ARB_internalformat_query = GL_TRUE; ctx->Extensions.ARB_map_buffer_range = GL_TRUE; @@ -777,4 +786,15 @@ void st_init_extensions(struct st_context *st) if (!ctx->Extensions.EXT_transform_feedback) ctx->Const.DisableVaryingPacking = GL_TRUE; } + + if (ctx->API == API_OPENGL_CORE) { + ctx->Const.MaxViewports = screen->get_param(screen, PIPE_CAP_MAX_VIEWPORTS); + if (ctx->Const.MaxViewports >= 16) { + ctx->Const.ViewportBounds.Min = -16384.0; + ctx->Const.ViewportBounds.Max = 16384.0; + ctx->Extensions.ARB_viewport_array = GL_TRUE; + } + } + if (ctx->Const.MaxProgramTextureGatherComponents > 0) + ctx->Extensions.ARB_texture_gather = GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index 90e9f2f78..5f951eb02 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -107,11 +107,11 @@ st_mesa_format_to_pipe_format(mesa_format mesaFormat) return PIPE_FORMAT_Z32_UNORM; case MESA_FORMAT_S8_UINT_Z24_UNORM: return PIPE_FORMAT_S8_UINT_Z24_UNORM; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: return PIPE_FORMAT_Z24_UNORM_S8_UINT; case MESA_FORMAT_X8Z24_UNORM: return PIPE_FORMAT_X8Z24_UNORM; - case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: return PIPE_FORMAT_Z24X8_UNORM; case MESA_FORMAT_S_UINT8: return PIPE_FORMAT_S8_UINT; @@ -465,9 +465,9 @@ st_pipe_format_to_mesa_format(enum pipe_format format) case PIPE_FORMAT_X8Z24_UNORM: return MESA_FORMAT_X8Z24_UNORM; case PIPE_FORMAT_Z24X8_UNORM: - return MESA_FORMAT_Z24_UNORM_S8_UINT; - case PIPE_FORMAT_Z24_UNORM_S8_UINT: return MESA_FORMAT_Z24_UNORM_X8_UINT; + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return MESA_FORMAT_Z24_UNORM_S8_UINT; case PIPE_FORMAT_Z32_FLOAT: return MESA_FORMAT_Z_FLOAT32; case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 610fc68a8..a9e75d8a6 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -87,7 +87,7 @@ extern "C" { */ #define MAX_ARRAYS 256 -/* will be 4 for GLSL 4.00 */ +/* if we support a native gallium TG4 with the ability to take 4 texoffsets then bump this */ #define MAX_GLSL_TEXTURE_OFFSET 1 class st_src_reg; @@ -249,7 +249,8 @@ public: int sampler; /**< sampler index */ int tex_target; /**< One of TEXTURE_*_INDEX */ GLboolean tex_shadow; - struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; + + st_src_reg tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; unsigned tex_offset_num_offset; int dead_mask; /**< Used in dead code elimination */ @@ -983,6 +984,7 @@ type_size(const struct glsl_type *type) } return size; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: /* Samplers take up one slot in UNIFORMS[], but they're baked in * at link time. */ @@ -2685,7 +2687,7 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) void glsl_to_tgsi_visitor::visit(ir_texture *ir) { - st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset, sample_index; + st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset, sample_index, component; st_dst_reg result_dst, coord_dst, cube_sc_dst; glsl_to_tgsi_instruction *inst = NULL; unsigned opcode = TGSI_OPCODE_NOP; @@ -2779,12 +2781,20 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) ir->lod_info.sample_index->accept(this); sample_index = this->result; break; + case ir_tg4: + opcode = TGSI_OPCODE_TG4; + ir->lod_info.component->accept(this); + component = this->result; + if (ir->offset) { + ir->offset->accept(this); + /* this should have been lowered */ + assert(ir->offset->type->base_type != GLSL_TYPE_ARRAY); + offset = this->result; + } + break; case ir_lod: assert(!"Unexpected ir_lod opcode"); break; - case ir_tg4: - assert(!"Unexpected ir_tg4 opcode"); - break; case ir_query_levels: assert(!"Unexpected ir_query_levels opcode"); break; @@ -2892,7 +2902,13 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) inst = emit(ir, opcode, result_dst, coord, lod_info); } else if (opcode == TGSI_OPCODE_TEX2) { inst = emit(ir, opcode, result_dst, coord, cube_sc); - } else + } else if (opcode == TGSI_OPCODE_TG4) { + if (is_cube_array && ir->shadow_comparitor) { + inst = emit(ir, opcode, result_dst, coord, cube_sc); + } else { + inst = emit(ir, opcode, result_dst, coord, component); + } + } else inst = emit(ir, opcode, result_dst, coord); if (ir->shadow_comparitor) @@ -2903,12 +2919,8 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) this->prog); if (ir->offset) { - inst->tex_offset_num_offset = 1; - inst->tex_offsets[0].Index = offset.index; - inst->tex_offsets[0].File = offset.file; - inst->tex_offsets[0].SwizzleX = GET_SWZ(offset.swizzle, 0); - inst->tex_offsets[0].SwizzleY = GET_SWZ(offset.swizzle, 1); - inst->tex_offsets[0].SwizzleZ = GET_SWZ(offset.swizzle, 2); + inst->tex_offset_num_offset = 1; + inst->tex_offsets[0] = offset; } switch (sampler_type->sampler_dimensionality) { @@ -3266,6 +3278,13 @@ glsl_to_tgsi_visitor::rename_temp_register(int index, int new_index) inst->src[j].index = new_index; } } + + for (j=0; j < inst->tex_offset_num_offset; j++) { + if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY && + inst->tex_offsets[j].index == index) { + inst->tex_offsets[j].index = new_index; + } + } if (inst->dst.file == PROGRAM_TEMPORARY && inst->dst.index == index) { inst->dst.index = new_index; @@ -3289,6 +3308,12 @@ glsl_to_tgsi_visitor::get_first_temp_read(int index) return (depth == 0) ? i : loop_start; } } + for (j=0; j < inst->tex_offset_num_offset; j++) { + if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY && + inst->tex_offsets[j].index == index) { + return (depth == 0) ? i : loop_start; + } + } if (inst->op == TGSI_OPCODE_BGNLOOP) { if(depth++ == 0) @@ -3350,6 +3375,11 @@ glsl_to_tgsi_visitor::get_last_temp_read(int index) last = (depth == 0) ? i : -2; } } + for (j=0; j < inst->tex_offset_num_offset; j++) { + if (inst->tex_offsets[j].file == PROGRAM_TEMPORARY && + inst->tex_offsets[j].index == index) + last = (depth == 0) ? i : -2; + } if (inst->op == TGSI_OPCODE_BGNLOOP) depth++; @@ -3726,6 +3756,26 @@ glsl_to_tgsi_visitor::eliminate_dead_code_advanced(void) } } } + for (unsigned i = 0; i < inst->tex_offset_num_offset; i++) { + if (inst->tex_offsets[i].file == PROGRAM_TEMPORARY && inst->tex_offsets[i].reladdr){ + /* Any temporary might be read, so no dead code elimination + * across this instruction. + */ + memset(writes, 0, sizeof(*writes) * this->next_temp * 4); + } else if (inst->tex_offsets[i].file == PROGRAM_TEMPORARY) { + /* Clear where it's used as src. */ + int src_chans = 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 0); + src_chans |= 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 1); + src_chans |= 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 2); + src_chans |= 1 << GET_SWZ(inst->tex_offsets[i].swizzle, 3); + + for (int c = 0; c < 4; c++) { + if (src_chans & (1 << c)) { + writes[4 * inst->tex_offsets[i].index + c] = NULL; + } + } + } + } break; } @@ -4079,7 +4129,7 @@ struct st_translate { struct ureg_dst address[2]; struct ureg_src samplers[PIPE_MAX_SAMPLERS]; struct ureg_src systemValues[SYSTEM_VALUE_MAX]; - + struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; unsigned array_sizes[MAX_ARRAYS]; const GLuint *inputMapping; @@ -4379,22 +4429,34 @@ translate_src(struct st_translate *t, const st_src_reg *src_reg) static struct tgsi_texture_offset translate_tex_offset(struct st_translate *t, - const struct tgsi_texture_offset *in_offset) + const st_src_reg *in_offset, int idx) { struct tgsi_texture_offset offset; struct ureg_src imm_src; - assert(in_offset->File == PROGRAM_IMMEDIATE); - imm_src = t->immediates[in_offset->Index]; - - offset.File = imm_src.File; - offset.Index = imm_src.Index; - offset.SwizzleX = imm_src.SwizzleX; - offset.SwizzleY = imm_src.SwizzleY; - offset.SwizzleZ = imm_src.SwizzleZ; - offset.File = TGSI_FILE_IMMEDIATE; - offset.Padding = 0; - + switch (in_offset->file) { + case PROGRAM_IMMEDIATE: + imm_src = t->immediates[in_offset->index]; + + offset.File = imm_src.File; + offset.Index = imm_src.Index; + offset.SwizzleX = imm_src.SwizzleX; + offset.SwizzleY = imm_src.SwizzleY; + offset.SwizzleZ = imm_src.SwizzleZ; + offset.Padding = 0; + break; + case PROGRAM_TEMPORARY: + imm_src = ureg_src(t->temps[in_offset->index]); + offset.File = imm_src.File; + offset.Index = imm_src.Index; + offset.SwizzleX = GET_SWZ(in_offset->swizzle, 0); + offset.SwizzleY = GET_SWZ(in_offset->swizzle, 1); + offset.SwizzleZ = GET_SWZ(in_offset->swizzle, 2); + offset.Padding = 0; + break; + default: + break; + } return offset; } @@ -4450,9 +4512,10 @@ compile_tgsi_instruction(struct st_translate *t, case TGSI_OPCODE_TEX2: case TGSI_OPCODE_TXB2: case TGSI_OPCODE_TXL2: + case TGSI_OPCODE_TG4: src[num_src++] = t->samplers[inst->sampler]; for (i = 0; i < inst->tex_offset_num_offset; i++) { - texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i]); + texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i], i); } tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow); @@ -5140,7 +5203,7 @@ get_mesa_program(struct gl_context *ctx, printf("GLSL IR for linked %s program %d:\n", _mesa_shader_stage_to_string(shader->Stage), shader_program->Name); - _mesa_print_ir(shader->ir, NULL); + _mesa_print_ir(stdout, shader->ir, NULL); printf("\n"); printf("\n"); fflush(stdout); @@ -5182,6 +5245,7 @@ get_mesa_program(struct gl_context *ctx, stgp->Base.InputType = shader_program->Geom.InputType; stgp->Base.OutputType = shader_program->Geom.OutputType; stgp->Base.VerticesOut = shader_program->Geom.VerticesOut; + stgp->Base.Invocations = shader_program->Geom.Invocations; break; default: assert(!"should not be reached"); @@ -5268,6 +5332,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) lower_packing_builtins(ir, lower_inst); } + lower_offset_arrays(ir); do_mat_op_to_vec(ir); lower_instructions(ir, MOD_TO_FRACT | diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 215b27634..6a776a8a2 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -30,6 +30,7 @@ #include "main/texobj.h" #include "main/teximage.h" #include "main/texstate.h" +#include "main/errors.h" #include "main/framebuffer.h" #include "main/fbobject.h" #include "main/renderbuffer.h" @@ -626,10 +627,14 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, return NULL; } - st->ctx->Debug.DebugOutput = GL_FALSE; if (attribs->flags & ST_CONTEXT_FLAG_DEBUG){ + struct gl_debug_state *debug = _mesa_get_debug_state(st->ctx); + if (!debug) { + *error = ST_CONTEXT_ERROR_NO_MEMORY; + return NULL; + } st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; - st->ctx->Debug.DebugOutput = GL_TRUE; + debug->DebugOutput = GL_TRUE; } if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index cadbe1705..e9074ac97 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -572,6 +572,11 @@ st_translate_fragment_program(struct st_context *st, input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; + case VARYING_SLOT_VIEWPORT: + input_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; case VARYING_SLOT_CLIP_DIST0: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 0; @@ -1027,6 +1032,10 @@ st_translate_geometry_program(struct st_context *st, gs_output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; gs_output_semantic_index[slot] = 0; break; + case VARYING_SLOT_VIEWPORT: + gs_output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; + gs_output_semantic_index[slot] = 0; + break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: @@ -1087,6 +1096,7 @@ st_translate_geometry_program(struct st_context *st, ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); + ureg_property_gs_invocations(ureg, stgp->Base.Invocations); if (stgp->glsl_to_tgsi) st_translate_program(st->ctx, diff --git a/mesalib/src/mesa/swrast/s_depth.c b/mesalib/src/mesa/swrast/s_depth.c index 93aaffc57..8c225e111 100644 --- a/mesalib/src/mesa/swrast/s_depth.c +++ b/mesalib/src/mesa/swrast/s_depth.c @@ -552,8 +552,8 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; mapMode = GL_MAP_WRITE_BIT; - if (rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || - rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || + if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || + rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || rb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM || rb->Format == MESA_FORMAT_X8Z24_UNORM) { mapMode |= GL_MAP_READ_BIT; @@ -602,8 +602,8 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_Z24_UNORM_S8_UINT: + case MESA_FORMAT_Z24_UNORM_X8_UINT: case MESA_FORMAT_S8_UINT_Z24_UNORM: case MESA_FORMAT_X8Z24_UNORM: { @@ -611,8 +611,8 @@ _swrast_clear_depth_buffer(struct gl_context *ctx) GLuint clearVal = 0; GLuint mask; - if (rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || - rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) + if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || + rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) mask = 0xff000000; else mask = 0xff; @@ -692,7 +692,7 @@ _swrast_clear_depth_stencil_buffer(struct gl_context *ctx) } switch (rb->Format) { - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: case MESA_FORMAT_S8_UINT_Z24_UNORM: { GLfloat zClear = (GLfloat) ctx->Depth.Clear; @@ -700,7 +700,7 @@ _swrast_clear_depth_stencil_buffer(struct gl_context *ctx) _mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear); - if (rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) { + if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) { mask = ((~writeMask) & 0xff) << 24; clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24; } diff --git a/mesalib/src/mesa/swrast/s_drawpix.c b/mesalib/src/mesa/swrast/s_drawpix.c index ed4487f3e..f7926e426 100644 --- a/mesalib/src/mesa/swrast/s_drawpix.c +++ b/mesalib/src/mesa/swrast/s_drawpix.c @@ -500,7 +500,7 @@ draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, /** - * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_X8_UINT + * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_S8_UINT * renderbuffer. No masking, zooming, scaling, etc. */ static void @@ -573,7 +573,7 @@ draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, if (depthRb == stencilRb && (depthRb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM || - depthRb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) && + depthRb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) && type == GL_UNSIGNED_INT_24_8 && !scaleOrBias && !zoom && diff --git a/mesalib/src/mesa/swrast/s_renderbuffer.c b/mesalib/src/mesa/swrast/s_renderbuffer.c index cf5e2230d..dfd3a6057 100644 --- a/mesalib/src/mesa/swrast/s_renderbuffer.c +++ b/mesalib/src/mesa/swrast/s_renderbuffer.c @@ -102,7 +102,7 @@ soft_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, rb->Format = MESA_FORMAT_Z_UNORM16; break; case GL_DEPTH_COMPONENT24: - rb->Format = MESA_FORMAT_Z24_UNORM_S8_UINT; + rb->Format = MESA_FORMAT_Z24_UNORM_X8_UINT; break; case GL_DEPTH_COMPONENT32: rb->Format = MESA_FORMAT_Z_UNORM32; diff --git a/mesalib/src/mesa/swrast/s_stencil.c b/mesalib/src/mesa/swrast/s_stencil.c index e7c35ff69..eba9da863 100644 --- a/mesalib/src/mesa/swrast/s_stencil.c +++ b/mesalib/src/mesa/swrast/s_stencil.c @@ -614,7 +614,7 @@ _swrast_clear_stencil_buffer(struct gl_context *ctx) } } break; - case MESA_FORMAT_Z24_UNORM_X8_UINT: + case MESA_FORMAT_Z24_UNORM_S8_UINT: { GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24; GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff; diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index 7a3e76f85..b620748c9 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -383,7 +383,7 @@ texfetch_funcs[] = fetch_texel_3d_f_z24_s8 }, { - MESA_FORMAT_Z24_UNORM_X8_UINT, + MESA_FORMAT_Z24_UNORM_S8_UINT, fetch_texel_1d_f_s8_z24, fetch_texel_2d_f_s8_z24, fetch_texel_3d_f_s8_z24 @@ -395,7 +395,7 @@ texfetch_funcs[] = fetch_texel_3d_f_z16 }, { - MESA_FORMAT_Z24_UNORM_S8_UINT, + MESA_FORMAT_Z24_UNORM_X8_UINT, fetch_texel_1d_f_s8_z24, fetch_texel_2d_f_s8_z24, fetch_texel_3d_f_s8_z24 diff --git a/mesalib/src/mesa/swrast/s_texfetch_tmp.h b/mesalib/src/mesa/swrast/s_texfetch_tmp.h index f3048894e..806f0fd1a 100644 --- a/mesalib/src/mesa/swrast/s_texfetch_tmp.h +++ b/mesalib/src/mesa/swrast/s_texfetch_tmp.h @@ -1556,8 +1556,8 @@ static void FETCH(f_s8_z24)( const struct swrast_texture_image *texImage, const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); const GLdouble scale = 1.0 / (GLdouble) 0xffffff; texel[0] = (GLfloat) (((*src) & 0x00ffffff) * scale); - ASSERT(texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_X8_UINT || - texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_S8_UINT); + ASSERT(texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_S8_UINT || + texImage->Base.TexFormat == MESA_FORMAT_Z24_UNORM_X8_UINT); ASSERT(texel[0] >= 0.0F); ASSERT(texel[0] <= 1.0F); } diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index 8e5af9627..2755ae62d 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -279,17 +279,18 @@ static void bind_inputs( struct gl_context *ctx, const void *ptr; if (inputs[i]->BufferObj->Name) { - if (!inputs[i]->BufferObj->Pointer) { + if (!inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer) { bo[*nr_bo] = inputs[i]->BufferObj; (*nr_bo)++; ctx->Driver.MapBufferRange(ctx, 0, inputs[i]->BufferObj->Size, GL_MAP_READ_BIT, - inputs[i]->BufferObj); + inputs[i]->BufferObj, + MAP_INTERNAL); - assert(inputs[i]->BufferObj->Pointer); + assert(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer); } - ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer, + ptr = ADD_POINTERS(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer, inputs[i]->Ptr); } else @@ -348,17 +349,19 @@ static void bind_indices( struct gl_context *ctx, return; } - if (_mesa_is_bufferobj(ib->obj) && !_mesa_bufferobj_mapped(ib->obj)) { + if (_mesa_is_bufferobj(ib->obj) && + !_mesa_bufferobj_mapped(ib->obj, MAP_INTERNAL)) { /* if the buffer object isn't mapped yet, map it now */ bo[*nr_bo] = ib->obj; (*nr_bo)++; ptr = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr, ib->count * vbo_sizeof_ib_type(ib->type), - GL_MAP_READ_BIT, ib->obj); - assert(ib->obj->Pointer); + GL_MAP_READ_BIT, ib->obj, + MAP_INTERNAL); + assert(ib->obj->Mappings[MAP_INTERNAL].Pointer); } else { /* user-space elements, or buffer already mapped */ - ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr); } if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) { @@ -403,7 +406,7 @@ static void unmap_vbos( struct gl_context *ctx, { GLuint i; for (i = 0; i < nr_bo; i++) { - ctx->Driver.UnmapBuffer(ctx, bo[i]); + ctx->Driver.UnmapBuffer(ctx, bo[i], MAP_INTERNAL); } } diff --git a/mesalib/src/mesa/vbo/vbo_exec_api.c b/mesalib/src/mesa/vbo/vbo_exec_api.c index 810913645..74aec127c 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_api.c +++ b/mesalib/src/mesa/vbo/vbo_exec_api.c @@ -998,7 +998,11 @@ void vbo_use_buffer_objects(struct gl_context *ctx) /* Allocate a real buffer object now */ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target); - if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj)) { + if (!ctx->Driver.BufferData(ctx, target, size, NULL, usage, + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT | + GL_CLIENT_STORAGE_BIT, + exec->vtx.bufferobj)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation"); } } @@ -1114,8 +1118,8 @@ void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) /* Free the vertex buffer. Unmap first if needed. */ - if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) { - ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj); + if (_mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) { + ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL); } _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); } diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index b316f097d..07ce08fef 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -53,7 +53,7 @@ check_buffers_are_unmapped(const struct gl_client_array **inputs) for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (inputs[i]) { struct gl_buffer_object *obj = inputs[i]->BufferObj; - assert(!_mesa_bufferobj_mapped(obj)); + assert(!_mesa_check_disallowed_mapping(obj)); (void) obj; } } @@ -73,7 +73,7 @@ vbo_check_buffers_are_unmapped(struct gl_context *ctx) /* check the current vertex arrays */ check_buffers_are_unmapped(exec->array.inputs); /* check the current glBegin/glVertex/glEnd-style VBO */ - assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj)); + assert(!_mesa_check_disallowed_mapping(exec->vtx.bufferobj)); } @@ -101,7 +101,8 @@ vbo_get_minmax_index(struct gl_context *ctx, if (_mesa_is_bufferobj(ib->obj)) { GLsizeiptr size = MIN2(count * index_size, ib->obj->Size); indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size, - GL_MAP_READ_BIT, ib->obj); + GL_MAP_READ_BIT, ib->obj, + MAP_INTERNAL); } switch (ib->type) { @@ -177,7 +178,7 @@ vbo_get_minmax_index(struct gl_context *ctx, } if (_mesa_is_bufferobj(ib->obj)) { - ctx->Driver.UnmapBuffer(ctx, ib->obj); + ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL); } } @@ -229,13 +230,15 @@ check_array_data(struct gl_context *ctx, struct gl_client_array *array, if (array->Enabled) { const void *data = array->Ptr; if (_mesa_is_bufferobj(array->BufferObj)) { - if (!array->BufferObj->Pointer) { + if (!array->BufferObj->Mappings[MAP_INTERNAL].Pointer) { /* need to map now */ - array->BufferObj->Pointer = + array->BufferObj->Mappings[MAP_INTERNAL].Pointer = ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size, - GL_MAP_READ_BIT, array->BufferObj); + GL_MAP_READ_BIT, array->BufferObj, + MAP_INTERNAL); } - data = ADD_POINTERS(data, array->BufferObj->Pointer); + data = ADD_POINTERS(data, + array->BufferObj->Mappings[MAP_INTERNAL].Pointer); } switch (array->Type) { case GL_FLOAT: @@ -273,8 +276,8 @@ unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array) { if (array->Enabled && _mesa_is_bufferobj(array->BufferObj) && - _mesa_bufferobj_mapped(array->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, array->BufferObj); + _mesa_bufferobj_mapped(array->BufferObj, MAP_INTERNAL)) { + ctx->Driver.UnmapBuffer(ctx, array->BufferObj, MAP_INTERNAL); } } @@ -295,7 +298,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType, elemMap = ctx->Driver.MapBufferRange(ctx, 0, ctx->Array.VAO->IndexBufferObj->Size, GL_MAP_READ_BIT, - ctx->Array.VAO->IndexBufferObj); + ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); elements = ADD_POINTERS(elements, elemMap); } @@ -324,7 +328,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType, } if (_mesa_is_bufferobj(vao->IndexBufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); } for (k = 0; k < Elements(vao->_VertexAttrib); k++) { @@ -374,7 +379,8 @@ print_draw_arrays(struct gl_context *ctx, if (bufName) { GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, - GL_MAP_READ_BIT, bufObj); + GL_MAP_READ_BIT, bufObj, + MAP_INTERNAL); int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr; float *f = (float *) (p + offset); int *k = (int *) f; @@ -386,7 +392,7 @@ print_draw_arrays(struct gl_context *ctx, for (i = 0; i < n; i++) { printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]); } - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); } } } @@ -885,7 +891,8 @@ dump_element_buffer(struct gl_context *ctx, GLenum type) ctx->Driver.MapBufferRange(ctx, 0, ctx->Array.VAO->IndexBufferObj->Size, GL_MAP_READ_BIT, - ctx->Array.VAO->IndexBufferObj); + ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); switch (type) { case GL_UNSIGNED_BYTE: { @@ -927,7 +934,8 @@ dump_element_buffer(struct gl_context *ctx, GLenum type) ; } - ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, + MAP_INTERNAL); } #endif diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c index 75115ce66..c454c6943 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_draw.c +++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c @@ -220,9 +220,10 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { /* a real buffer obj: Ptr is an offset, not a pointer*/ - assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */ + assert(exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Pointer); assert(offset >= 0); - arrays[attr].Ptr = (GLubyte *)exec->vtx.bufferobj->Offset + offset; + arrays[attr].Ptr = (GLubyte *) + exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Offset + offset; } else { /* Ptr into ordinary app memory */ @@ -261,12 +262,15 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) struct gl_context *ctx = exec->ctx; if (ctx->Driver.FlushMappedBufferRange) { - GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset; - GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float); + GLintptr offset = exec->vtx.buffer_used - + exec->vtx.bufferobj->Mappings[MAP_INTERNAL].Offset; + GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * + sizeof(float); if (length) ctx->Driver.FlushMappedBufferRange(ctx, offset, length, - exec->vtx.bufferobj); + exec->vtx.bufferobj, + MAP_INTERNAL); } exec->vtx.buffer_used += (exec->vtx.buffer_ptr - @@ -275,7 +279,7 @@ vbo_exec_vtx_unmap( struct vbo_exec_context *exec ) assert(exec->vtx.buffer_used <= VBO_VERT_BUFFER_SIZE); assert(exec->vtx.buffer_ptr != NULL); - ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj); + ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL); exec->vtx.buffer_map = NULL; exec->vtx.buffer_ptr = NULL; exec->vtx.max_vert = 0; @@ -312,7 +316,8 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) (VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used), accessRange, - exec->vtx.bufferobj); + exec->vtx.bufferobj, + MAP_INTERNAL); exec->vtx.buffer_ptr = exec->vtx.buffer_map; } else { @@ -325,14 +330,19 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) exec->vtx.buffer_used = 0; if (ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER_ARB, - VBO_VERT_BUFFER_SIZE, - NULL, usage, exec->vtx.bufferobj)) { + VBO_VERT_BUFFER_SIZE, + NULL, usage, + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT | + GL_CLIENT_STORAGE_BIT, + exec->vtx.bufferobj)) { /* buffer allocation worked, now map the buffer */ exec->vtx.buffer_map = (GLfloat *)ctx->Driver.MapBufferRange(ctx, 0, VBO_VERT_BUFFER_SIZE, accessRange, - exec->vtx.bufferobj); + exec->vtx.bufferobj, + MAP_INTERNAL); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation"); diff --git a/mesalib/src/mesa/vbo/vbo_primitive_restart.c b/mesalib/src/mesa/vbo/vbo_primitive_restart.c index 9c3055431..25c89669c 100644 --- a/mesalib/src/mesa/vbo/vbo_primitive_restart.c +++ b/mesalib/src/mesa/vbo/vbo_primitive_restart.c @@ -177,7 +177,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, struct _mesa_prim temp_prim; struct vbo_context *vbo = vbo_context(ctx); vbo_draw_func draw_prims_func = vbo->draw_prims; - GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer; + GLboolean map_ib = ib->obj->Name && !ib->obj->Mappings[MAP_INTERNAL].Pointer; void *ptr; /* If there is an indirect buffer, map it and extract the draw params */ @@ -186,7 +186,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, struct _mesa_index_buffer new_ib = *ib; const uint32_t *indirect_params; if (!ctx->Driver.MapBufferRange(ctx, 0, indirect->Size, GL_MAP_READ_BIT, - indirect)) { + indirect, MAP_INTERNAL)) { /* something went wrong with mapping, give up */ _mesa_error(ctx, GL_OUT_OF_MEMORY, @@ -195,8 +195,9 @@ vbo_sw_primitive_restart(struct gl_context *ctx, } assert(nr_prims == 1); - indirect_params = (const uint32_t *) ADD_POINTERS(indirect->Pointer, - new_prim.indirect_offset); + indirect_params = (const uint32_t *) + ADD_POINTERS(indirect->Mappings[MAP_INTERNAL].Pointer, + new_prim.indirect_offset); new_prim.is_indirect = 0; new_prim.count = indirect_params[0]; @@ -210,7 +211,7 @@ vbo_sw_primitive_restart(struct gl_context *ctx, prims = &new_prim; ib = &new_ib; - ctx->Driver.UnmapBuffer(ctx, indirect); + ctx->Driver.UnmapBuffer(ctx, indirect, MAP_INTERNAL); } /* Find the sub-primitives. These are regions in the index buffer which @@ -218,17 +219,17 @@ vbo_sw_primitive_restart(struct gl_context *ctx, */ if (map_ib) { ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT, - ib->obj); + ib->obj, MAP_INTERNAL); } - ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr); sub_prims = find_sub_primitives(ptr, vbo_sizeof_ib_type(ib->type), 0, ib->count, restart_index, &num_sub_prims); if (map_ib) { - ctx->Driver.UnmapBuffer(ctx, ib->obj); + ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL); } /* Loop over the primitives, and use the located sub-primitives to draw diff --git a/mesalib/src/mesa/vbo/vbo_rebase.c b/mesalib/src/mesa/vbo/vbo_rebase.c index c700621ce..f3fe5f757 100644 --- a/mesalib/src/mesa/vbo/vbo_rebase.c +++ b/mesalib/src/mesa/vbo/vbo_rebase.c @@ -157,15 +157,16 @@ void vbo_rebase_prims( struct gl_context *ctx, } else if (ib) { /* Unfortunately need to adjust each index individually. */ - GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer; + GLboolean map_ib = ib->obj->Name && + !ib->obj->Mappings[MAP_INTERNAL].Pointer; void *ptr; if (map_ib) ctx->Driver.MapBufferRange(ctx, 0, ib->obj->Size, GL_MAP_READ_BIT, - ib->obj); + ib->obj, MAP_INTERNAL); - ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr); /* Some users might prefer it if we translated elements to * GLuints here. Others wouldn't... @@ -183,7 +184,7 @@ void vbo_rebase_prims( struct gl_context *ctx, } if (map_ib) - ctx->Driver.UnmapBuffer(ctx, ib->obj); + ctx->Driver.UnmapBuffer(ctx, ib->obj, MAP_INTERNAL); tmp_ib.obj = ctx->Shared->NullBufferObj; tmp_ib.ptr = tmp_indices; diff --git a/mesalib/src/mesa/vbo/vbo_save_api.c b/mesalib/src/mesa/vbo/vbo_save_api.c index 98ab68623..1c6b91942 100644 --- a/mesalib/src/mesa/vbo/vbo_save_api.c +++ b/mesalib/src/mesa/vbo/vbo_save_api.c @@ -200,6 +200,8 @@ alloc_vertex_store(struct gl_context *ctx) GL_ARRAY_BUFFER_ARB, VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat), NULL, GL_STATIC_DRAW_ARB, + GL_MAP_WRITE_BIT | + GL_DYNAMIC_STORAGE_BIT, vertex_store->bufferobj); } else { @@ -251,7 +253,8 @@ vbo_save_map_vertex_store(struct gl_context *ctx, GLsizeiptr size = vertex_store->bufferobj->Size - offset; GLfloat *range = (GLfloat *) ctx->Driver.MapBufferRange(ctx, offset, size, access, - vertex_store->bufferobj); + vertex_store->bufferobj, + MAP_INTERNAL); if (range) { /* compute address of start of whole buffer (needed elsewhere) */ vertex_store->buffer = range - vertex_store->used; @@ -277,13 +280,14 @@ vbo_save_unmap_vertex_store(struct gl_context *ctx, if (vertex_store->bufferobj->Size > 0) { GLintptr offset = 0; GLsizeiptr length = vertex_store->used * sizeof(GLfloat) - - vertex_store->bufferobj->Offset; + - vertex_store->bufferobj->Mappings[MAP_INTERNAL].Offset; /* Explicitly flush the region we wrote to */ ctx->Driver.FlushMappedBufferRange(ctx, offset, length, - vertex_store->bufferobj); + vertex_store->bufferobj, + MAP_INTERNAL); - ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj); + ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj, MAP_INTERNAL); } vertex_store->buffer = NULL; } @@ -1116,6 +1120,7 @@ _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, { GET_CURRENT_CONTEXT(ctx); struct vbo_save_context *save = &vbo_context(ctx)->save; + struct gl_buffer_object *indexbuf = ctx->Array.VAO->IndexBufferObj; GLint i; if (!_mesa_is_valid_prim_mode(ctx, mode)) { @@ -1138,9 +1143,9 @@ _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, _ae_map_vbos(ctx); - if (_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) + if (_mesa_is_bufferobj(indexbuf)) indices = - ADD_POINTERS(ctx->Array.VAO->IndexBufferObj->Pointer, indices); + ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices); vbo_save_NotifyBegin(ctx, (mode | VBO_SAVE_PRIM_WEAK | VBO_SAVE_PRIM_NO_CURRENT_UPDATE)); diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c index 4b13cc4e5..89fd30e0f 100644 --- a/mesalib/src/mesa/vbo/vbo_save_draw.c +++ b/mesalib/src/mesa/vbo/vbo_save_draw.c @@ -225,7 +225,8 @@ vbo_save_loopback_vertex_list(struct gl_context *ctx, ctx->Driver.MapBufferRange(ctx, 0, list->vertex_store->bufferobj->Size, GL_MAP_READ_BIT, /* ? */ - list->vertex_store->bufferobj); + list->vertex_store->bufferobj, + MAP_INTERNAL); vbo_loopback_vertex_list(ctx, (const GLfloat *)(buffer + list->buffer_offset), @@ -235,7 +236,8 @@ vbo_save_loopback_vertex_list(struct gl_context *ctx, list->wrap_count, list->vertex_size); - ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj); + ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj, + MAP_INTERNAL); } diff --git a/mesalib/src/mesa/vbo/vbo_split_copy.c b/mesalib/src/mesa/vbo/vbo_split_copy.c index 4332ef2e6..719ad651a 100644 --- a/mesalib/src/mesa/vbo/vbo_split_copy.c +++ b/mesalib/src/mesa/vbo/vbo_split_copy.c @@ -451,11 +451,14 @@ replay_init( struct copy_context *copy ) copy->varying[j].size = attr_size(copy->array[i]); copy->vertex_size += attr_size(copy->array[i]); - if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) - ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo); + if (_mesa_is_bufferobj(vbo) && + !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) + ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo, + MAP_INTERNAL); - copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer, - copy->array[i]->Ptr); + copy->varying[j].src_ptr = + ADD_POINTERS(vbo->Mappings[MAP_INTERNAL].Pointer, + copy->array[i]->Ptr); copy->dstarray_ptr[i] = ©->varying[j].dstarray; } @@ -466,12 +469,13 @@ replay_init( struct copy_context *copy ) * do it internally. */ if (_mesa_is_bufferobj(copy->ib->obj) && - !_mesa_bufferobj_mapped(copy->ib->obj)) + !_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) ctx->Driver.MapBufferRange(ctx, 0, copy->ib->obj->Size, GL_MAP_READ_BIT, - copy->ib->obj); + copy->ib->obj, MAP_INTERNAL); - srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer, - copy->ib->ptr); + srcptr = (const GLubyte *) + ADD_POINTERS(copy->ib->obj->Mappings[MAP_INTERNAL].Pointer, + copy->ib->ptr); switch (copy->ib->type) { case GL_UNSIGNED_BYTE: @@ -572,15 +576,15 @@ replay_finish( struct copy_context *copy ) */ for (i = 0; i < copy->nr_varying; i++) { struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj; - if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo)) - ctx->Driver.UnmapBuffer(ctx, vbo); + if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) + ctx->Driver.UnmapBuffer(ctx, vbo, MAP_INTERNAL); } /* Unmap index buffer: */ if (_mesa_is_bufferobj(copy->ib->obj) && - _mesa_bufferobj_mapped(copy->ib->obj)) { - ctx->Driver.UnmapBuffer(ctx, copy->ib->obj); + _mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) { + ctx->Driver.UnmapBuffer(ctx, copy->ib->obj, MAP_INTERNAL); } } -- cgit v1.2.3