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/drivers/common/meta.c | 1964 ++++++++------------------- mesalib/src/mesa/drivers/common/meta.h | 361 +++++ mesalib/src/mesa/drivers/common/meta_blit.c | 825 +++++++++++ 3 files changed, 1721 insertions(+), 1429 deletions(-) create mode 100644 mesalib/src/mesa/drivers/common/meta_blit.c (limited to 'mesalib/src/mesa/drivers/common') 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; +} -- cgit v1.2.3