aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/drivers/common
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/drivers/common')
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c1868
-rw-r--r--mesalib/src/mesa/drivers/common/meta.h361
-rw-r--r--mesalib/src/mesa/drivers/common/meta_blit.c825
3 files changed, 1673 insertions, 1381 deletions
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;
-};
-
-
-/**
- * State for glClear()
- */
-struct clear_state
-{
- GLuint VAO;
- GLuint VBO;
- GLuint ShaderProg;
- GLint ColorLocation;
- GLint LayerLocation;
-
- GLuint IntegerShaderProg;
- GLint IntegerColorLocation;
- GLint IntegerLayerLocation;
-};
+static struct blit_shader *
+choose_blit_shader(GLenum target, struct blit_shader_table *table);
-
-/**
- * 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;
@@ -425,6 +162,182 @@ link_program_with_debug(struct gl_context *ctx, GLuint program)
}
/**
+ * 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) {
@@ -1375,20 +1304,18 @@ setup_copypix_texture(struct gl_context *ctx,
/**
* 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)
+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);
- 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);
/* copy pixel data to texture */
if (newTex) {
@@ -1422,617 +1349,24 @@ setup_drawpix_texture(struct gl_context *ctx,
}
}
-
-
-/**
- * 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)
+void
+_mesa_meta_setup_ff_tnl_for_blit(GLuint *VAO, GLuint *VBO,
+ unsigned texcoord_size)
{
- 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);
- }
+ _mesa_meta_setup_vertex_objects(VAO, VBO, false, 2, texcoord_size, 0);
/* 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 {
- 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;
-
- }
-
- /* 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);
-
- /* 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);
- }
-
- _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);
- }
- }
-
- 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);
- }
-}
-
-static void
-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_DeleteObjectARB(blit->ShaderProg);
- blit->ShaderProg = 0;
- _mesa_DeleteObjectARB(blit->RectShaderProg);
- blit->RectShaderProg = 0;
-
- _mesa_DeleteTextures(1, &blit->depthTex.TexObj);
- blit->depthTex.TexObj = 0;
-}
-
-
-/**
* Meta implementation of ctx->Driver.Clear() in terms of polygon rendering.
*/
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);
-
- /* create vertex array buffer */
- _mesa_GenBuffers(1, &clear->VBO);
- _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, clear->VBO);
+ _mesa_meta_setup_vertex_objects(&clear->VAO, &clear->VBO, true, 3, 0, 0);
- /* 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 */
+ _mesa_meta_setup_vertex_objects(&copypix->VAO, &copypix->VBO, false,
+ 3, 2, 0);
- /* create vertex array object */
- _mesa_GenVertexArrays(1, &copypix->VAO);
- _mesa_BindVertexArray(copypix->VAO);
-
- /* create vertex array buffer */
- _mesa_GenBuffers(1, &copypix->VBO);
- _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, copypix->VBO);
- _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts),
- NULL, GL_DYNAMIC_DRAW_ARB);
+ /* Silence valgrind warnings about reading uninitialized stack. */
+ memset(verts, 0, sizeof(verts));
- /* 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);
- }
-
- 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 */
+ _mesa_meta_setup_vertex_objects(&bitmap->VAO, &bitmap->VBO, false, 3, 2, 4);
- /* create vertex array object */
- _mesa_GenVertexArrays(1, &bitmap->VAO);
- _mesa_BindVertexArray(bitmap->VAO);
+ newTex = _mesa_meta_alloc_texture(tex, width, height, texIntFormat);
- /* 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);
-
- /* 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 = 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;
+}