diff options
Diffstat (limited to 'mesalib/src')
36 files changed, 1877 insertions, 670 deletions
diff --git a/mesalib/src/gallium/auxiliary/Makefile.am b/mesalib/src/gallium/auxiliary/Makefile.am index a4eee4773..49792930a 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.am +++ b/mesalib/src/gallium/auxiliary/Makefile.am @@ -45,3 +45,9 @@ util/u_format_srgb.c: $(srcdir)/util/u_format_srgb.py util/u_format_table.c: $(srcdir)/util/u_format_table.py $(srcdir)/util/u_format_pack.py $(srcdir)/util/u_format_parse.py $(srcdir)/util/u_format.csv $(AM_V_GEN) $(PYTHON2) $(srcdir)/util/u_format_table.py $(srcdir)/util/u_format.csv > $@ + +# XXX: As a work around for https://bugs.freedesktop.org/show_bug.cgi?id=59334 +# clover needs to link against libgallium.a. Delete this once we have a real +# fix for this bug. +all-local: libgallium.la + ln -f $(builddir)/.libs/libgallium.a $(builddir)/libgallium.a diff --git a/mesalib/src/gallium/auxiliary/util/u_pack_color.h b/mesalib/src/gallium/auxiliary/util/u_pack_color.h index 6c6d9669c..1f6a56a33 100644 --- a/mesalib/src/gallium/auxiliary/util/u_pack_color.h +++ b/mesalib/src/gallium/auxiliary/util/u_pack_color.h @@ -52,6 +52,7 @@ union util_color { ubyte ub; ushort us; uint ui; + ushort h[4]; /* half float */ float f[4]; double d[4]; }; diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c index 5f0134d70..7e3666122 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.c @@ -316,13 +316,39 @@ util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe, /** - * Make simple fragment color pass-through shader. + * Make simple fragment color pass-through shader that replicates OUT[0] + * to all bound colorbuffers. */ void * -util_make_fragment_passthrough_shader(struct pipe_context *pipe) +util_make_fragment_passthrough_shader(struct pipe_context *pipe, + int input_semantic, + int input_interpolate) { - return util_make_fragment_cloneinput_shader(pipe, 1, TGSI_SEMANTIC_COLOR, - TGSI_INTERPOLATE_PERSPECTIVE); + static const char shader_templ[] = + "FRAG\n" + "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" + "DCL IN[0], %s[0], %s\n" + "DCL OUT[0], COLOR[0]\n" + + "MOV OUT[0], IN[0]\n" + "END\n"; + + char text[sizeof(shader_templ)+100]; + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + sprintf(text, shader_templ, tgsi_semantic_names[input_semantic], + tgsi_interpolate_names[input_interpolate]); + + if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + assert(0); + return NULL; + } +#if 0 + tgsi_dump(state.tokens, 0); +#endif + + return pipe->create_fs_state(pipe, &state); } diff --git a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h index e4ffde652..22b9cee4d 100644 --- a/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/mesalib/src/gallium/auxiliary/util/u_simple_shaders.h @@ -87,7 +87,9 @@ util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe, extern void * -util_make_fragment_passthrough_shader(struct pipe_context *pipe); +util_make_fragment_passthrough_shader(struct pipe_context *pipe, + int input_semantic, + int input_interpolate); extern void * diff --git a/mesalib/src/mapi/glapi/gen/ARB_internalformat_query.xml b/mesalib/src/mapi/glapi/gen/ARB_internalformat_query.xml new file mode 100644 index 000000000..70a2a3109 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_internalformat_query.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<category name="GL_ARB_internalformat_query" number="112"> + <!-- Other existing enums are reused for this extension. --> + + <enum name="NUM_SAMPLE_COUNTS" value="0x9380"/> + + <function name="GetInternalformativ" offset="assign" static_dispatch="false" + es2="3.0"> + <param name="target" type="GLenum"/> + <param name="internalformat" type="GLenum"/> + <param name="pname" type="GLenum"/> + <param name="bufSize" type="GLsizei"/> + <param name="params" type="GLint *"/> + </function> +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index adbeea613..f9a67d2ca 100755 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8298,13 +8298,15 @@ </function> </category> -<!-- ARB extensions #110...#112 --> +<!-- ARB extensions #110...#116 --> + +<xi:include href="ARB_internalformat_query.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <category name="GL_ARB_map_buffer_alignment" number="113"> <enum name="MIN_MAP_BUFFER_ALIGNMENT" value="0x90BC" /> </category> -<!-- ARB extensions #114...#116 --> +<xi:include href="ARB_base_instance.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <xi:include href="ARB_texture_storage.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> diff --git a/mesalib/src/mapi/glapi/gen/gl_genexec.py b/mesalib/src/mapi/glapi/gen/gl_genexec.py index da9ae716a..a85b4471a 100644 --- a/mesalib/src/mapi/glapi/gen/gl_genexec.py +++ b/mesalib/src/mapi/glapi/gen/gl_genexec.py @@ -108,6 +108,7 @@ header = """/** #include "main/shaderapi.h" #include "main/uniforms.h" #include "main/syncobj.h" +#include "main/formatquery.h" #include "main/dispatch.h" diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c index 93fa3c745..3de5199b4 100644 --- a/mesalib/src/mesa/drivers/common/driverfuncs.c +++ b/mesalib/src/mesa/drivers/common/driverfuncs.c @@ -91,6 +91,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) /* Texture functions */ driver->ChooseTextureFormat = _mesa_choose_tex_format; + driver->QuerySamplesForFormat = NULL; driver->TexImage = _mesa_store_teximage; driver->TexSubImage = _mesa_store_texsubimage; driver->GetTexImage = _mesa_meta_GetTexImage; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index d211fda9d..e25481e1a 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -54,6 +54,7 @@ #include "main/pixel.h" #include "main/pbo.h" #include "main/polygon.h" +#include "main/queryobj.h" #include "main/readpix.h" #include "main/scissor.h" #include "main/shaderapi.h" @@ -89,6 +90,9 @@ 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; @@ -222,6 +226,9 @@ struct blit_state GLuint ArrayObj; GLuint VBO; GLuint DepthFP; + GLuint ShaderProg; + GLuint RectShaderProg; + struct temp_texture depthTex; }; @@ -478,6 +485,15 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) if (save->TransformFeedbackNeedsResume) _mesa_PauseTransformFeedback(); + /* After saving the current occlusion object, call EndQuery so that no + * occlusion querying will be active during the meta-operation. + */ + if (state & MESA_META_OCCLUSION_QUERY) { + save->CurrentOcclusionObject = ctx->Query.CurrentOcclusionObject; + if (save->CurrentOcclusionObject) + _mesa_EndQuery(save->CurrentOcclusionObject->Target); + } + if (state & MESA_META_ALPHA_TEST) { save->AlphaEnabled = ctx->Color.AlphaEnabled; save->AlphaFunc = ctx->Color.AlphaFunc; @@ -806,6 +822,18 @@ _mesa_meta_end(struct gl_context *ctx) struct save_state *save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth - 1]; const GLbitfield state = save->SavedState; + /* After starting a new occlusion query, initialize the results to the + * values saved previously. The driver will then continue to increment + * these values. + */ + if (state & MESA_META_OCCLUSION_QUERY) { + if (save->CurrentOcclusionObject) { + _mesa_BeginQuery(save->CurrentOcclusionObject->Target, + save->CurrentOcclusionObject->Id); + ctx->Query.CurrentOcclusionObject->Result = save->CurrentOcclusionObject->Result; + } + } + if (state & MESA_META_ALPHA_TEST) { if (ctx->Color.AlphaEnabled != save->AlphaEnabled) _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled); @@ -1144,7 +1172,7 @@ static void init_temp_texture(struct gl_context *ctx, struct temp_texture *tex) { /* prefer texture rectangle */ - if (ctx->Extensions.NV_texture_rectangle) { + if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle) { tex->Target = GL_TEXTURE_RECTANGLE; tex->MaxSize = ctx->Const.MaxTextureRectSize; tex->NPOT = GL_TRUE; @@ -1205,6 +1233,21 @@ get_bitmap_temp_texture(struct gl_context *ctx) return tex; } +/** + * 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 *tex = &ctx->Meta->Blit.depthTex; + + if (!tex->TexObj) { + init_temp_texture(ctx, tex); + } + + return tex; +} /** * Compute the width/height of texture needed to draw an image of the @@ -1269,7 +1312,8 @@ alloc_texture(struct temp_texture *tex, * Setup/load texture for glCopyPixels or glBlitFramebuffer. */ static void -setup_copypix_texture(struct temp_texture *tex, +setup_copypix_texture(struct gl_context *ctx, + struct temp_texture *tex, GLboolean newTex, GLint srcX, GLint srcY, GLsizei width, GLsizei height, GLenum intFormat, @@ -1278,7 +1322,8 @@ setup_copypix_texture(struct temp_texture *tex, _mesa_BindTexture(tex->Target, tex->TexObj); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter); - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); /* copy framebuffer image to texture */ if (newTex) { @@ -1321,7 +1366,8 @@ setup_drawpix_texture(struct gl_context *ctx, _mesa_BindTexture(tex->Target, tex->TexObj); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + if (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); /* copy pixel data to texture */ if (newTex) { @@ -1388,6 +1434,158 @@ init_blit_depth_pixels(struct gl_context *ctx) strlen(program2), (const GLubyte *) program2); } +static void +setup_ff_blit_framebuffer(struct gl_context *ctx, + struct blit_state *blit) +{ + struct vertex { + GLfloat x, y, s, t; + }; + struct vertex verts[4]; + + if (blit->ArrayObj == 0) { + /* one-time setup */ + + /* create vertex array object */ + _mesa_GenVertexArrays(1, &blit->ArrayObj); + _mesa_BindVertexArray(blit->ArrayObj); + + /* create vertex array buffer */ + _mesa_GenBuffers(1, &blit->VBO); + _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); + _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), + NULL, GL_DYNAMIC_DRAW_ARB); + + /* setup vertex arrays */ + _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); + _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); + _mesa_EnableClientState(GL_VERTEX_ARRAY); + _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); + } + + /* setup projection matrix */ + _mesa_MatrixMode(GL_PROJECTION); + _mesa_LoadIdentity(); + _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + +} + +static void +setup_glsl_blit_framebuffer(struct gl_context *ctx, + struct blit_state *blit, + GLenum target) +{ + struct vertex { + GLfloat x, y, s, t; + }; + struct vertex verts[4]; + const char *vs_source; + char *fs_source; + GLuint vs, fs; + void *mem_ctx; + GLuint ShaderProg; + GLboolean texture_2d = (target == GL_TEXTURE_2D); + + /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */ + assert(_mesa_is_desktop_gl(ctx) || texture_2d); + + /* Check if already initialized */ + if (blit->ArrayObj == 0) { + + /* create vertex array object */ + _mesa_GenVertexArrays(1, &blit->ArrayObj); + _mesa_BindVertexArray(blit->ArrayObj); + + /* 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)); + } + + /* 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, + "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" + "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"); + _mesa_EnableVertexAttribArray(0); + _mesa_EnableVertexAttribArray(1); + 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. @@ -1401,17 +1599,22 @@ 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) + 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 = - &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]]; + 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; @@ -1420,13 +1623,22 @@ blitframebuffer_texture(struct gl_context *ctx, GLuint sampler, samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; - - 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; + 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) { @@ -1434,6 +1646,23 @@ blitframebuffer_texture(struct gl_context *ctx, 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, &ctx->Meta->Blit); + } + + _mesa_BindVertexArray(blit->ArrayObj); + _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); + _mesa_GenSamplers(1, &sampler); _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); @@ -1463,8 +1692,10 @@ blitframebuffer_texture(struct gl_context *ctx, GL_SKIP_DECODE_EXT); } - _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - _mesa_set_enable(ctx, target, GL_TRUE); + 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) */ { @@ -1490,14 +1721,15 @@ blitframebuffer_texture(struct gl_context *ctx, t1 = srcY1; } - verts[0].x = (GLfloat) dstX0; - verts[0].y = (GLfloat) dstY0; - verts[1].x = (GLfloat) dstX1; - verts[1].y = (GLfloat) dstY0; - verts[2].x = (GLfloat) dstX1; - verts[2].y = (GLfloat) dstY1; - verts[3].x = (GLfloat) dstX0; - verts[3].y = (GLfloat) dstY1; + /* 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; @@ -1511,6 +1743,10 @@ blitframebuffer_texture(struct gl_context *ctx, _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); } + /* setup viewport */ + _mesa_set_viewport(ctx, 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 @@ -1545,18 +1781,31 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx, { 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 GLboolean srcFlipX = srcX1 < srcX0; - const GLboolean srcFlipY = 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 @@ -1570,105 +1819,122 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx, return; } - if (srcFlipX) { - GLint tmp = dstX0; - dstX0 = dstX1; - dstX1 = tmp; - } - - if (srcFlipY) { - GLint tmp = dstY0; - dstY0 = dstY1; - dstY1 = tmp; - } - /* only scissor effects blit so save/clear all other relevant state */ _mesa_meta_begin(ctx, ~MESA_META_SCISSOR); - if (blit->ArrayObj == 0) { - /* one-time setup */ - - /* create vertex array object */ - _mesa_GenVertexArrays(1, &blit->ArrayObj); - _mesa_BindVertexArray(blit->ArrayObj); - - /* 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); - } - else { - _mesa_BindVertexArray(blit->ArrayObj); - _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - } - /* Try faster, direct texture approach first */ mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter); + dstX0, dstY0, dstX1, dstY1, mask, filter, + dstFlipX, dstFlipY, use_glsl_version); if (mask == 0x0) { _mesa_meta_end(ctx); return; } - /* Continue with "normal" approach which involves copying the src rect - * into a temporary texture and is "blitted" by drawing a textured quad. + /* 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(ctx, blit); + } - newTex = alloc_texture(tex, srcW, srcH, GL_RGBA); + _mesa_BindVertexArray(blit->ArrayObj); + _mesa_BindBuffer(GL_ARRAY_BUFFER_ARB, blit->VBO); - /* vertex positions/texcoords (after texture allocation!) */ + /* Continue with "normal" approach which involves copying the src rect + * into a temporary texture and is "blitted" by drawing a textured quad. + */ { - verts[0].x = (GLfloat) dstX0; - verts[0].y = (GLfloat) dstY0; - verts[1].x = (GLfloat) dstX1; - verts[1].y = (GLfloat) dstY0; - verts[2].x = (GLfloat) dstX1; - verts[2].y = (GLfloat) dstY1; - verts[3].x = (GLfloat) dstX0; - verts[3].y = (GLfloat) dstY1; + /* 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 = 0.0F; - verts[0].t = 0.0F; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; - - /* upload new vertex data */ - _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); } - _mesa_set_enable(ctx, tex->Target, GL_TRUE); + /* 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) { - setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH, - GL_RGBA, filter); + 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); + + newTex = alloc_texture(tex, srcW, srcH, rb_base_format); + setup_copypix_texture(ctx, tex, newTex, srcX, srcY, srcW, srcH, + rb_base_format, filter); + /* texcoords (after texture allocation!) */ + { + verts[0].s = 0.0F; + verts[0].t = 0.0F; + verts[1].s = tex->Sright; + verts[1].t = 0.0F; + verts[2].s = tex->Sright; + verts[2].t = tex->Ttop; + verts[3].s = 0.0F; + verts[3].t = tex->Ttop; + + /* upload new vertex data */ + _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); + } + + _mesa_set_viewport(ctx, 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) { + 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) { + /* 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); /* maybe change tex format here */ - newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT); + 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, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH, + setup_drawpix_texture(ctx, depthTex, newTex, GL_DEPTH_COMPONENT, srcW, srcH, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp); _mesa_BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); @@ -1678,6 +1944,8 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx, _mesa_DepthFunc(GL_ALWAYS); _mesa_DepthMask(GL_TRUE); + _mesa_set_viewport(ctx, 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; @@ -1689,7 +1957,8 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx, /* XXX can't easily do stencil */ } - _mesa_set_enable(ctx, tex->Target, GL_FALSE); + if (_mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES) + _mesa_set_enable(ctx, tex->Target, GL_FALSE); _mesa_meta_end(ctx); @@ -1712,6 +1981,14 @@ meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit) _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; } @@ -1987,7 +2264,8 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) MESA_META_VIEWPORT | MESA_META_CLIP | MESA_META_CLAMP_FRAGMENT_COLOR | - MESA_META_MULTISAMPLE); + MESA_META_MULTISAMPLE | + MESA_META_OCCLUSION_QUERY); if (!(buffers & BUFFER_BITS_COLOR)) { /* We'll use colormask to disable color writes. Otherwise, @@ -2171,7 +2449,7 @@ _mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, } /* Alloc/setup texture */ - setup_copypix_texture(tex, newTex, srcX, srcY, width, height, + setup_copypix_texture(ctx, tex, newTex, srcX, srcY, width, height, GL_RGBA, GL_NEAREST); _mesa_set_enable(ctx, tex->Target, GL_TRUE); diff --git a/mesalib/src/mesa/drivers/common/meta.h b/mesalib/src/mesa/drivers/common/meta.h index 6ffc5b56a..a6bdd3947 100644 --- a/mesalib/src/mesa/drivers/common/meta.h +++ b/mesalib/src/mesa/drivers/common/meta.h @@ -57,6 +57,7 @@ #define MESA_META_SELECT_FEEDBACK 0x80000 #define MESA_META_MULTISAMPLE 0x100000 #define MESA_META_FRAMEBUFFER_SRGB 0x200000 +#define MESA_META_OCCLUSION_QUERY 0x400000 /**\}*/ extern void diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 9cebcea92..9ed9df4b3 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -189,6 +189,7 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api, mesa_api = API_OPENGLES; break; case __DRI_API_GLES2: + case __DRI_API_GLES3: mesa_api = API_OPENGLES2; break; case __DRI_API_OPENGL_CORE: diff --git a/mesalib/src/mesa/drivers/dri/common/drisw_util.c b/mesalib/src/mesa/drivers/dri/common/drisw_util.c index 33339880b..62bdd88d1 100644 --- a/mesalib/src/mesa/drivers/dri/common/drisw_util.c +++ b/mesalib/src/mesa/drivers/dri/common/drisw_util.c @@ -124,6 +124,7 @@ driCreateContextAttribs(__DRIscreen *screen, int api, mesa_api = API_OPENGLES; break; case __DRI_API_GLES2: + case __DRI_API_GLES3: mesa_api = API_OPENGLES2; break; case __DRI_API_OPENGL_CORE: diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 107711560..a9cd7382e 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -136,10 +136,24 @@ get_buffer(struct gl_context *ctx, const char *func, GLenum target) } -static inline GLbitfield -default_access_mode(const struct gl_context *ctx) +/** + * Convert a GLbitfield describing the mapped buffer access flags + * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY. + */ +static GLenum +simplified_access_mode(struct gl_context *ctx, GLbitfield access) { - /* Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says: + const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; + if ((access & rwFlags) == rwFlags) + return GL_READ_WRITE; + if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT) + return GL_READ_ONLY; + if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT) + return GL_WRITE_ONLY; + + /* Otherwise, AccessFlags is zero (the default state). + * + * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says: * * Name Type Initial Value Legal Values * ... ... ... ... @@ -155,26 +169,9 @@ default_access_mode(const struct gl_context *ctx) * The difference is because GL_OES_mapbuffer only supports mapping buffers * write-only. */ - return _mesa_is_gles(ctx) - ? GL_MAP_WRITE_BIT : (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); -} + assert(access == 0); - -/** - * Convert a GLbitfield describing the mapped buffer access flags - * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY. - */ -static GLenum -simplified_access_mode(GLbitfield access) -{ - const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; - if ((access & rwFlags) == rwFlags) - return GL_READ_WRITE; - if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT) - return GL_READ_ONLY; - if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT) - return GL_WRITE_ONLY; - return GL_READ_WRITE; /* this should never happen, but no big deal */ + return _mesa_is_gles(ctx) ? GL_WRITE_ONLY : GL_READ_WRITE; } @@ -354,7 +351,7 @@ _mesa_initialize_buffer_object( struct gl_context *ctx, obj->RefCount = 1; obj->Name = name; obj->Usage = GL_STATIC_DRAW_ARB; - obj->AccessFlags = default_access_mode(ctx); + obj->AccessFlags = 0; } @@ -864,7 +861,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) if (_mesa_bufferobj_mapped(bufObj)) { /* if mapped, unmap it now */ ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = default_access_mode(ctx); + bufObj->AccessFlags = 0; bufObj->Pointer = NULL; } @@ -1064,7 +1061,7 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, if (_mesa_bufferobj_mapped(bufObj)) { /* Unmap the existing buffer. We'll replace it now. Not an error. */ ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = default_access_mode(ctx); + bufObj->AccessFlags = 0; ASSERT(bufObj->Pointer == NULL); } @@ -1282,7 +1279,7 @@ _mesa_UnmapBuffer(GLenum target) #endif status = ctx->Driver.UnmapBuffer( ctx, bufObj ); - bufObj->AccessFlags = default_access_mode(ctx); + bufObj->AccessFlags = 0; ASSERT(bufObj->Pointer == NULL); ASSERT(bufObj->Offset == 0); ASSERT(bufObj->Length == 0); @@ -1310,7 +1307,7 @@ _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(bufObj->AccessFlags); + *params = simplified_access_mode(ctx, bufObj->AccessFlags); return; case GL_BUFFER_MAPPED_ARB: *params = _mesa_bufferobj_mapped(bufObj); @@ -1364,7 +1361,7 @@ _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(bufObj->AccessFlags); + *params = simplified_access_mode(ctx, bufObj->AccessFlags); return; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index d10a57394..87848fb93 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -94,7 +94,7 @@ supported_buffer_bitmask(const struct gl_context *ctx, * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. */ static GLbitfield -draw_buffer_enum_to_bitmask(GLenum buffer) +draw_buffer_enum_to_bitmask(const struct gl_context *ctx, GLenum buffer) { switch (buffer) { case GL_NONE: @@ -102,6 +102,21 @@ draw_buffer_enum_to_bitmask(GLenum buffer) case GL_FRONT: return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; case GL_BACK: + if (_mesa_is_gles3(ctx)) { + /* Page 181 (page 192 of the PDF) in section 4.2.1 of the OpenGL + * ES 3.0.1 specification says: + * + * "When draw buffer zero is BACK, color values are written + * into the sole buffer for single-buffered contexts, or into + * the back buffer for double-buffered contexts." + * + * Since there is no stereo rendering in ES 3.0, only return the + * LEFT bits. This also satisfies the "n must be 1" requirement. + */ + if (ctx->DrawBuffer->Visual.doubleBufferMode) + return BUFFER_BIT_BACK_LEFT; + return BUFFER_BIT_FRONT_LEFT; + } return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; case GL_RIGHT: return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; @@ -241,7 +256,7 @@ _mesa_DrawBuffer(GLenum buffer) else { const GLbitfield supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); - destMask = draw_buffer_enum_to_bitmask(buffer); + destMask = draw_buffer_enum_to_bitmask(ctx, buffer); if (destMask == BAD_MASK) { /* totally bogus buffer */ _mesa_error(ctx, GL_INVALID_ENUM, @@ -290,6 +305,10 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) /* Turns out n==0 is a valid input that should not produce an error. * The remaining code below correctly handles the n==0 case. + * + * From the OpenGL 3.0 specification, page 258: + * "An INVALID_VALUE error is generated if n is greater than + * MAX_DRAW_BUFFERS." */ if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); @@ -299,26 +318,94 @@ _mesa_DrawBuffers(GLsizei n, const GLenum *buffers) supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer); usedBufferMask = 0x0; + /* From the ES 3.0 specification, page 180: + * "If the GL is bound to the default framebuffer, then n must be 1 + * and the constant must be BACK or NONE." + */ + if (_mesa_is_gles3(ctx) && _mesa_is_winsys_fbo(ctx->DrawBuffer) && + (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); + return; + } + /* complicated error checking... */ for (output = 0; output < n; output++) { if (buffers[output] == GL_NONE) { destMask[output] = 0x0; } else { - destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); - if (destMask[output] == BAD_MASK - || _mesa_bitcount(destMask[output]) > 1) { + /* Page 259 (page 275 of the PDF) in section 4.2.1 of the OpenGL 3.0 + * spec (20080923) says: + * + * "If the GL is bound to a framebuffer object and DrawBuffers is + * supplied with [...] COLOR_ATTACHMENTm where m is greater than + * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error + * INVALID_OPERATION results." + */ + if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >= + GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)"); + return; + } + + destMask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]); + + /* From the OpenGL 3.0 specification, page 258: + * "Each buffer listed in bufs must be one of the values from tables + * 4.5 or 4.6. Otherwise, an INVALID_ENUM error is generated. + */ + if (destMask[output] == BAD_MASK) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); return; } + + /* From the OpenGL 3.0 specification, page 259: + * "For both the default framebuffer and framebuffer objects, the + * constants FRONT, BACK, LEFT, RIGHT, and FRONT_AND_BACK are not + * valid in the bufs array passed to DrawBuffers, and will result in + * the error INVALID_OPERATION. This restriction is because these + * constants may themselves refer to multiple buffers, as shown in + * table 4.4." + */ + if (_mesa_bitcount(destMask[output]) > 1) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)"); + return; + } + + /* From the OpenGL 3.0 specification, page 259: + * "If the GL is bound to the default framebuffer and DrawBuffers is + * supplied with a constant (other than NONE) that does not indicate + * any of the color buffers allocated to the GL context by the window + * system, the error INVALID_OPERATION will be generated. + * + * If the GL is bound to a framebuffer object and DrawBuffers is + * supplied with a constant from table 4.6 [...] then the error + * INVALID_OPERATION results." + */ destMask[output] &= supportedMask; if (destMask[output] == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(unsupported buffer)"); return; } + + /* ES 3.0 is even more restrictive. From the ES 3.0 spec, page 180: + * "If the GL is bound to a framebuffer object, the ith buffer listed + * in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION." + */ + if (_mesa_is_gles3(ctx) && _mesa_is_user_fbo(ctx->DrawBuffer) && + buffers[output] != GL_NONE && + buffers[output] != GL_COLOR_ATTACHMENT0 + output) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)"); + return; + } + + /* From the OpenGL 3.0 specification, page 258: + * "Except for NONE, a buffer may not appear more than once in the + * array pointed to by bufs. Specifying a buffer more then once will + * result in the error INVALID_OPERATION." + */ if (destMask[output] & usedBufferMask) { - /* can't specify a dest buffer more than once! */ _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(duplicated buffer)"); return; @@ -391,7 +478,7 @@ _mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers, const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb); GLuint output; for (output = 0; output < n; output++) { - mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); + mask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]); ASSERT(mask[output] != BAD_MASK); mask[output] &= supportedMask; } diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 70c53240e..07787d41d 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -201,6 +201,22 @@ struct dd_function_table { GLenum srcFormat, GLenum srcType ); /** + * Determine sample counts support for a particular format + * + * \param ctx GL context + * \param internalFormat GL format enum + * \param samples Buffer to hold the returned sample counts. + * Drivers \b must \b not return more than 16 counts. + * + * \returns + * The number of sample counts actually written to \c samples. If + * \c internaFormat is not renderable, zero is returned. + */ + size_t (*QuerySamplesForFormat)(struct gl_context *ctx, + GLenum internalFormat, + int samples[16]); + + /** * Called by glTexImage[123]D() and glCopyTexImage[12]D() * Allocate texture memory and copy the user's image to the buffer. * The gl_texture_image fields, etc. will be fully initialized. diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index c3c73fc26..23b494836 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -104,6 +104,7 @@ static const struct extension extension_table[] = { { "GL_ARB_half_float_pixel", o(ARB_half_float_pixel), GL, 2003 }, { "GL_ARB_half_float_vertex", o(ARB_half_float_vertex), GL, 2008 }, { "GL_ARB_instanced_arrays", o(ARB_instanced_arrays), GL, 2008 }, + { "GL_ARB_internalformat_query", o(ARB_internalformat_query), GL, 2011 }, { "GL_ARB_invalidate_subdata", o(dummy_true), GL, 2012 }, { "GL_ARB_map_buffer_alignment", o(ARB_map_buffer_alignment), GL, 2011 }, { "GL_ARB_map_buffer_range", o(ARB_map_buffer_range), GL, 2008 }, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 50ad84c56..9db5035d1 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -245,6 +245,25 @@ _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, { assert(_mesa_is_winsys_fbo(fb)); + if (_mesa_is_gles3(ctx)) { + assert(attachment == GL_BACK || + attachment == GL_DEPTH || + attachment == GL_STENCIL); + switch (attachment) { + case GL_BACK: + /* Since there is no stereo rendering in ES 3.0, only return the + * LEFT bits. + */ + if (ctx->DrawBuffer->Visual.doubleBufferMode) + return &fb->Attachment[BUFFER_BACK_LEFT]; + return &fb->Attachment[BUFFER_FRONT_LEFT]; + case GL_DEPTH: + return &fb->Attachment[BUFFER_DEPTH]; + case GL_STENCIL: + return &fb->Attachment[BUFFER_STENCIL]; + } + } + switch (attachment) { case GL_FRONT_LEFT: return &fb->Attachment[BUFFER_FRONT_LEFT]; @@ -492,7 +511,8 @@ _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat) case GL_LUMINANCE_ALPHA: case GL_INTENSITY: case GL_ALPHA: - return ctx->Extensions.ARB_framebuffer_object; + return ctx->API == API_OPENGL_COMPAT && + ctx->Extensions.ARB_framebuffer_object; case GL_RED: case GL_RG: return ctx->Extensions.ARB_texture_rg; @@ -1110,7 +1130,7 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RGB16: return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0; case GL_SRGB8_EXT: - return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGB : 0; + return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0; case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: @@ -1197,25 +1217,21 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; case GL_R16F: case GL_R32F: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg && ctx->Extensions.ARB_texture_float) ? GL_RED : 0; case GL_RG16F: case GL_RG32F: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && + return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg && ctx->Extensions.ARB_texture_float) ? GL_RG : 0; case GL_RGB16F: case GL_RGB32F: return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float) - || _mesa_is_gles3(ctx) ? GL_RGB : 0; case GL_RGBA16F: case GL_RGBA32F: return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float) - || _mesa_is_gles3(ctx) ? GL_RGBA : 0; case GL_ALPHA16F_ARB: case GL_ALPHA32F_ARB: @@ -1240,10 +1256,10 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RGB9_E5: return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_shared_exponent) - || _mesa_is_gles3(ctx) ? GL_RGB : 0; + ? GL_RGB : 0; case GL_R11F_G11F_B10F: return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) - || _mesa_is_gles3(ctx) ? GL_RGB : 0; + ? GL_RGB : 0; case GL_RGBA8UI_EXT: case GL_RGBA16UI_EXT: @@ -1378,13 +1394,28 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei samples) { const char *func = samples == NO_SAMPLES ? - "glRenderbufferStorage" : "RenderbufferStorageMultisample"; + "glRenderbufferStorage" : "glRenderbufferStorageMultisample"; struct gl_renderbuffer *rb; GLenum baseFormat; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); + if (MESA_VERBOSE & VERBOSE_API) { + if (samples == NO_SAMPLES) + _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n", + func, + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(internalFormat), + width, height); + else + _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n", + func, + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(internalFormat), + width, height, samples); + } + if (target != GL_RENDERBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); return; @@ -1904,6 +1935,10 @@ _mesa_CheckFramebufferStatus(GLenum target) ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n", + _mesa_lookup_enum_by_nr(target)); + buffer = get_framebuffer_target(ctx, target); if (!buffer) { _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); @@ -2347,11 +2382,19 @@ _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, * OES_framebuffer_object spec refers to the EXT_framebuffer_object * spec. */ - if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) { + if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) + && !_mesa_is_gles3(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetFramebufferAttachmentParameteriv(bound FBO = 0)"); return; } + + if (_mesa_is_gles3(ctx) && attachment != GL_BACK && + attachment != GL_DEPTH && attachment != GL_STENCIL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferAttachmentParameteriv(attachment)"); + return; + } /* the default / window-system FBO */ att = _mesa_get_fb0_attachment(ctx, buffer, attachment); } @@ -2739,7 +2782,6 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); const struct gl_framebuffer *readFb, *drawFb; - const struct gl_renderbuffer *colorReadRb, *colorDrawRb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -2794,8 +2836,10 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, /* get color read/draw renderbuffers */ if (mask & GL_COLOR_BUFFER_BIT) { - colorReadRb = readFb->_ColorReadBuffer; - colorDrawRb = drawFb->_ColorDrawBuffers[0]; + const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers; + const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; + const struct gl_renderbuffer *colorDrawRb = NULL; + GLuint i; /* From the EXT_framebuffer_object spec: * @@ -2803,20 +2847,45 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, * the read and draw framebuffers, the corresponding bit is silently * ignored." */ - if ((colorReadRb == NULL) || (colorDrawRb == NULL)) { - colorReadRb = colorDrawRb = NULL; - mask &= ~GL_COLOR_BUFFER_BIT; + if (!colorReadRb || numColorDrawBuffers == 0) { + mask &= ~GL_COLOR_BUFFER_BIT; } - else if (!compatible_color_datatypes(colorReadRb->Format, - colorDrawRb->Format)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(color buffer datatypes mismatch)"); - return; + else { + for (i = 0; i < numColorDrawBuffers; i++) { + colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; + if (!colorDrawRb) + continue; + + if (!compatible_color_datatypes(colorReadRb->Format, + colorDrawRb->Format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(color buffer datatypes mismatch)"); + return; + } + /* extra checks for multisample copies... */ + if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { + /* color formats must match */ + if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); + return; + } + } + } + if (filter == GL_LINEAR) { + /* 3.1 spec, page 199: + * "Calling BlitFramebuffer will result in an INVALID_OPERATION error + * if filter is LINEAR and read buffer contains integer data." + */ + GLenum type = _mesa_get_format_datatype(colorReadRb->Format); + if (type == GL_INT || type == GL_UNSIGNED_INT) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(integer color type)"); + return; + } + } } } - else { - colorReadRb = colorDrawRb = NULL; - } if (mask & GL_STENCIL_BUFFER_BIT) { struct gl_renderbuffer *readRb = @@ -2833,14 +2902,35 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_STENCIL_BUFFER_BIT; } - else if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != - _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { - /* There is no need to check the stencil datatype here, because - * there is only one: GL_UNSIGNED_INT. - */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(stencil buffer size mismatch)"); - return; + else { + int read_z_bits, draw_z_bits; + + if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != + _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { + /* There is no need to check the stencil datatype here, because + * there is only one: GL_UNSIGNED_INT. + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebuffer(stencil attachment format mismatch)"); + return; + } + + read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS); + draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS); + + /* If both buffers also have depth data, the depth formats must match + * as well. If one doesn't have depth, it's not blitted, so we should + * ignore the depth format check. + */ + if (read_z_bits > 0 && draw_z_bits > 0 && + (read_z_bits != draw_z_bits || + _mesa_get_format_datatype(readRb->Format) != + _mesa_get_format_datatype(drawRb->Format))) { + + _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" + "(stencil attachment depth format mismatch)"); + return; + } } } @@ -2859,13 +2949,30 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, if ((readRb == NULL) || (drawRb == NULL)) { mask &= ~GL_DEPTH_BUFFER_BIT; } - else if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != - _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || - (_mesa_get_format_datatype(readRb->Format) != - _mesa_get_format_datatype(drawRb->Format))) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(depth buffer format mismatch)"); - return; + else { + int read_s_bit, draw_s_bit; + + if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != + _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) || + (_mesa_get_format_datatype(readRb->Format) != + _mesa_get_format_datatype(drawRb->Format))) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebuffer(depth attachment format mismatch)"); + return; + } + + read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS); + draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS); + + /* If both buffers also have stencil data, the stencil formats must + * match as well. If one doesn't have stencil, it's not blitted, so + * we should ignore the stencil format check. + */ + if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer" + "(depth attachment stencil bits mismatch)"); + return; + } } } @@ -2886,28 +2993,6 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); return; } - - /* color formats must match */ - if (colorReadRb && - colorDrawRb && - !compatible_resolve_formats(colorReadRb, colorDrawRb)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); - return; - } - } - - if (filter == GL_LINEAR && (mask & GL_COLOR_BUFFER_BIT)) { - /* 3.1 spec, page 199: - * "Calling BlitFramebuffer will result in an INVALID_OPERATION error - * if filter is LINEAR and read buffer contains integer data." - */ - GLenum type = _mesa_get_format_datatype(colorReadRb->Format); - if (type == GL_INT || type == GL_UNSIGNED_INT) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(integer color type)"); - return; - } } if (!ctx->Extensions.EXT_framebuffer_blit) { @@ -2917,6 +3002,10 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, /* Debug code */ if (DEBUG_BLIT) { + const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer; + const struct gl_renderbuffer *colorDrawRb = NULL; + GLuint i = 0; + printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," " 0x%x, 0x%x)\n", srcX0, srcY0, srcX1, srcY1, @@ -2938,18 +3027,25 @@ _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } printf("\n"); - att = find_attachment(drawFb, colorDrawRb); - printf(" Dst FBO %u RB %u (%dx%d) ", - drawFb->Name, colorDrawRb->Name, - colorDrawRb->Width, colorDrawRb->Height); - if (att && att->Texture) { - printf("Tex %u tgt 0x%x level %u face %u", - att->Texture->Name, - att->Texture->Target, - att->TextureLevel, - att->CubeMapFace); + /* Print all active color render buffers */ + for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { + colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i]; + if (!colorDrawRb) + continue; + + att = find_attachment(drawFb, colorDrawRb); + printf(" Dst FBO %u RB %u (%dx%d) ", + drawFb->Name, colorDrawRb->Name, + colorDrawRb->Width, colorDrawRb->Height); + if (att && att->Texture) { + printf("Tex %u tgt 0x%x level %u face %u", + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); + } + printf("\n"); } - printf("\n"); } } diff --git a/mesalib/src/mesa/main/formatquery.c b/mesalib/src/mesa/main/formatquery.c new file mode 100644 index 000000000..f08ab66f0 --- /dev/null +++ b/mesalib/src/mesa/main/formatquery.c @@ -0,0 +1,147 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "mtypes.h" +#include "glformats.h" +#include "macros.h" +#include "mfeatures.h" +#include "enums.h" +#include "fbobject.h" +#include "formatquery.h" + +void GLAPIENTRY +_mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, + GLsizei bufSize, GLint *params) +{ + GLint buffer[16]; + GLsizei count = 0; + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_internalformat_query) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInternalformativ"); + return; + } + + assert(ctx->Driver.QuerySamplesForFormat != NULL); + + /* The ARB_internalformat_query spec says: + * + * "If the <target> parameter to GetInternalformativ is not one of + * TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY or RENDERBUFFER + * then an INVALID_ENUM error is generated." + */ + switch (target) { + case GL_RENDERBUFFER: + break; + + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + /* Mesa does not currently support GL_ARB_texture_multisample, so these + * enums are not valid on this implementation either. + */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetInternalformativ(target=%s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + /* The ARB_internalformat_query spec says: + * + * "If the <internalformat> parameter to GetInternalformativ is not + * color-, depth- or stencil-renderable, then an INVALID_ENUM error is + * generated." + */ + if (_mesa_base_fbo_format(ctx, internalformat) == 0) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetInternalformativ(internalformat=%s)", + _mesa_lookup_enum_by_nr(internalformat)); + return; + } + + /* The ARB_internalformat_query spec says: + * + * "If the <bufSize> parameter to GetInternalformativ is negative, then + * an INVALID_VALUE error is generated." + */ + if (bufSize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetInternalformativ(target=%s)", + _mesa_lookup_enum_by_nr(target)); + return; + } + + switch (pname) { + case GL_SAMPLES: + count = ctx->Driver.QuerySamplesForFormat(ctx, internalformat, buffer); + break; + case GL_NUM_SAMPLE_COUNTS: { + /* The driver can return 0, and we should pass that along to the + * application. The ARB decided that ARB_internalformat_query should + * behave as ARB_internalformat_query2 in this situation. + * + * The ARB_internalformat_query2 spec says: + * + * "- NUM_SAMPLE_COUNTS: The number of sample counts that would be + * returned by querying SAMPLES is returned in <params>. + * * If <internalformat> is not color-renderable, + * depth-renderable, or stencil-renderable (as defined in + * section 4.4.4), or if <target> does not support multiple + * samples (ie other than TEXTURE_2D_MULTISAMPLE, + * TEXTURE_2D_MULTISAMPLE_ARRAY, or RENDERBUFFER), 0 is + * returned." + */ + const size_t num_samples = + ctx->Driver.QuerySamplesForFormat(ctx, internalformat, buffer); + + /* QuerySamplesForFormat writes some stuff to buffer, so we have to + * separately over-write it with the requested value. + */ + buffer[0] = (GLint) num_samples; + count = 1; + break; + } + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetInternalformativ(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); + return; + } + + if (bufSize != 0 && params == NULL) { + /* Emit a warning to aid application debugging, but go ahead and do the + * memcpy (and probably crash) anyway. + */ + _mesa_warning(ctx, + "glGetInternalformativ(bufSize = %d, but params = NULL)", + bufSize); + } + + /* Copy the data from the temporary buffer to the buffer supplied by the + * application. Clamp the size of the copy to the size supplied by the + * application. + */ + memcpy(params, buffer, MIN2(count, bufSize) * sizeof(GLint)); + + return; +} diff --git a/mesalib/src/mesa/main/formatquery.h b/mesalib/src/mesa/main/formatquery.h new file mode 100644 index 000000000..585c3eb64 --- /dev/null +++ b/mesalib/src/mesa/main/formatquery.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once +#ifndef FORMATQUERY_H +#define FORMATQUERY_H + +#include "compiler.h" +#include "glheader.h" + +extern void GLAPIENTRY +_mesa_GetInternalformativ(GLenum target, GLenum internalformat, + GLenum pname, GLsizei bufSize, GLint *params); + +#endif /* FORMATQUERY_H */ diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 13887f8f5..8cbfbd6bc 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -42,6 +42,7 @@ #include "framebuffer.h" #include "renderbuffer.h" #include "texobj.h" +#include "glformats.h" @@ -899,6 +900,26 @@ _mesa_get_color_read_type(struct gl_context *ctx) /** + * Returns the read renderbuffer for the specified format. + */ +struct gl_renderbuffer * +_mesa_get_read_renderbuffer_for_format(struct gl_context *ctx, + GLenum format) +{ + struct gl_framebuffer *rfb = ctx->ReadBuffer; + + if (_mesa_is_color_format(format)) { + return rfb->Attachment[rfb->_ColorReadBufferIndex].Renderbuffer; + } else if (_mesa_is_depth_format(format) || + _mesa_is_depthstencil_format(format)) { + return rfb->Attachment[BUFFER_DEPTH].Renderbuffer; + } else { + return rfb->Attachment[BUFFER_STENCIL].Renderbuffer; + } +} + + +/** * Print framebuffer info to stderr, for debugging. */ void diff --git a/mesalib/src/mesa/main/framebuffer.h b/mesalib/src/mesa/main/framebuffer.h index ad53d8cbe..06db04925 100644 --- a/mesalib/src/mesa/main/framebuffer.h +++ b/mesalib/src/mesa/main/framebuffer.h @@ -30,6 +30,7 @@ struct gl_config; struct gl_context; +struct gl_renderbuffer; extern struct gl_framebuffer * _mesa_create_framebuffer(const struct gl_config *visual); @@ -96,6 +97,10 @@ _mesa_get_color_read_type(struct gl_context *ctx); extern GLenum _mesa_get_color_read_format(struct gl_context *ctx); +extern struct gl_renderbuffer * +_mesa_get_read_renderbuffer_for_format(struct gl_context *ctx, + GLenum format); + extern void _mesa_print_framebuffer(const struct gl_framebuffer *fb); diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index ff56ffad0..7969f77a4 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -1289,6 +1289,10 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, ctx->Extensions.ARB_texture_rgb10_a2ui) { break; /* OK */ } + if (type == GL_UNSIGNED_INT_2_10_10_10_REV && format == GL_RGB && + ctx->API == API_OPENGLES2) { + break; /* OK by GL_EXT_texture_type_2_10_10_10_REV */ + } return GL_INVALID_OPERATION; case GL_UNSIGNED_INT_24_8: @@ -1402,6 +1406,10 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: return GL_NO_ERROR; + case GL_UNSIGNED_INT_2_10_10_10_REV: + /* OK by GL_EXT_texture_type_2_10_10_10_REV */ + return (ctx->API == API_OPENGLES2) + ? GL_NO_ERROR : GL_INVALID_ENUM; case GL_HALF_FLOAT: return ctx->Extensions.ARB_half_float_pixel ? GL_NO_ERROR : GL_INVALID_ENUM; @@ -1478,8 +1486,18 @@ _mesa_error_check_format_and_type(const struct gl_context *ctx, else if (ctx->Extensions.ARB_depth_buffer_float && type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) return GL_NO_ERROR; - else + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_INVALID_OPERATION; + default: return GL_INVALID_ENUM; + } case GL_DUDV_ATI: case GL_DU8DV8_ATI: @@ -1670,3 +1688,442 @@ _mesa_es_error_check_format_and_type(GLenum format, GLenum type, return type_valid ? GL_NO_ERROR : GL_INVALID_OPERATION; } + + +/** + * Do error checking of format/type combinations for OpenGL ES 3 + * glTex[Sub]Image. + * \return error code, or GL_NO_ERROR. + */ +GLenum +_mesa_es3_error_check_format_and_type(GLenum format, GLenum type, + GLenum internalFormat, + unsigned dimensions) +{ + GLboolean type_valid = GL_TRUE; + + switch (format) { + case GL_RGBA: + switch (type) { + case GL_UNSIGNED_BYTE: + switch (internalFormat) { + case GL_RGBA: + case GL_RGBA8: + case GL_RGB5_A1: + case GL_RGBA4: + case GL_SRGB8_ALPHA8_EXT: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_BYTE: + if (internalFormat != GL_RGBA8_SNORM) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_SHORT_4_4_4_4: + switch (internalFormat) { + case GL_RGBA: + case GL_RGBA4: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_UNSIGNED_SHORT_5_5_5_1: + switch (internalFormat) { + case GL_RGBA: + case GL_RGB5_A1: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_UNSIGNED_INT_2_10_10_10_REV: + switch (internalFormat) { + case GL_RGBA: /* GL_EXT_texture_type_2_10_10_10_REV */ + case GL_RGB10_A2: + case GL_RGB5_A1: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_HALF_FLOAT: + if (internalFormat != GL_RGBA16F) + return GL_INVALID_OPERATION; + break; + + case GL_FLOAT: + switch (internalFormat) { + case GL_RGBA16F: + case GL_RGBA32F: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_RGBA_INTEGER: + switch (type) { + case GL_UNSIGNED_BYTE: + if (internalFormat != GL_RGBA8UI) + return GL_INVALID_OPERATION; + break; + + case GL_BYTE: + if (internalFormat != GL_RGBA8I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_SHORT: + if (internalFormat != GL_RGBA16UI) + return GL_INVALID_OPERATION; + break; + + case GL_SHORT: + if (internalFormat != GL_RGBA16I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_INT: + if (internalFormat != GL_RGBA32UI) + return GL_INVALID_OPERATION; + break; + + case GL_INT: + if (internalFormat != GL_RGBA32I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (internalFormat != GL_RGB10_A2UI) + return GL_INVALID_OPERATION; + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_RGB: + switch (type) { + case GL_UNSIGNED_BYTE: + switch (internalFormat) { + case GL_RGB: + case GL_RGB8: + case GL_RGB565: + case GL_SRGB8: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_BYTE: + if (internalFormat != GL_RGB8_SNORM) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_SHORT_5_6_5: + switch (internalFormat) { + case GL_RGB: + case GL_RGB565: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_UNSIGNED_INT_10F_11F_11F_REV: + if (internalFormat != GL_R11F_G11F_B10F) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_INT_5_9_9_9_REV: + if (internalFormat != GL_RGB9_E5) + return GL_INVALID_OPERATION; + break; + + case GL_HALF_FLOAT: + switch (internalFormat) { + case GL_RGB16F: + case GL_R11F_G11F_B10F: + case GL_RGB9_E5: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_FLOAT: + switch (internalFormat) { + case GL_RGB16F: + case GL_RGB32F: + case GL_R11F_G11F_B10F: + case GL_RGB9_E5: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_UNSIGNED_INT_2_10_10_10_REV: + switch (internalFormat) { + case GL_RGB: /* GL_EXT_texture_type_2_10_10_10_REV */ + break; + default: + return GL_INVALID_OPERATION; + } + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_RGB_INTEGER: + switch (type) { + case GL_UNSIGNED_BYTE: + if (internalFormat != GL_RGB8UI) + return GL_INVALID_OPERATION; + break; + + case GL_BYTE: + if (internalFormat != GL_RGB8I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_SHORT: + if (internalFormat != GL_RGB16UI) + return GL_INVALID_OPERATION; + break; + + case GL_SHORT: + if (internalFormat != GL_RGB16I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_INT: + if (internalFormat != GL_RGB32UI) + return GL_INVALID_OPERATION; + break; + + case GL_INT: + if (internalFormat != GL_RGB32I) + return GL_INVALID_OPERATION; + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_RG: + switch (type) { + case GL_UNSIGNED_BYTE: + if (internalFormat != GL_RG8) + return GL_INVALID_OPERATION; + break; + + case GL_BYTE: + if (internalFormat != GL_RG8_SNORM) + return GL_INVALID_OPERATION; + break; + + case GL_HALF_FLOAT: + if (internalFormat != GL_RG16F) + return GL_INVALID_OPERATION; + break; + + case GL_FLOAT: + switch (internalFormat) { + case GL_RG16F: + case GL_RG32F: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_RG_INTEGER: + switch (type) { + case GL_UNSIGNED_BYTE: + if (internalFormat != GL_RG8UI) + return GL_INVALID_OPERATION; + break; + + case GL_BYTE: + if (internalFormat != GL_RG8I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_SHORT: + if (internalFormat != GL_RG16UI) + return GL_INVALID_OPERATION; + break; + + case GL_SHORT: + if (internalFormat != GL_RG16I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_INT: + if (internalFormat != GL_RG32UI) + return GL_INVALID_OPERATION; + break; + + case GL_INT: + if (internalFormat != GL_RG32I) + return GL_INVALID_OPERATION; + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_RED: + switch (type) { + case GL_UNSIGNED_BYTE: + if (internalFormat != GL_R8) + return GL_INVALID_OPERATION; + break; + + case GL_BYTE: + if (internalFormat != GL_R8_SNORM) + return GL_INVALID_OPERATION; + break; + + case GL_HALF_FLOAT: + if (internalFormat != GL_R16F) + return GL_INVALID_OPERATION; + break; + + case GL_FLOAT: + switch (internalFormat) { + case GL_R16F: + case GL_R32F: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_RED_INTEGER: + switch (type) { + case GL_UNSIGNED_BYTE: + if (internalFormat != GL_R8UI) + return GL_INVALID_OPERATION; + break; + + case GL_BYTE: + if (internalFormat != GL_R8I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_SHORT: + if (internalFormat != GL_R16UI) + return GL_INVALID_OPERATION; + break; + + case GL_SHORT: + if (internalFormat != GL_R16I) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_INT: + if (internalFormat != GL_R32UI) + return GL_INVALID_OPERATION; + break; + + case GL_INT: + if (internalFormat != GL_R32I) + return GL_INVALID_OPERATION; + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_DEPTH_COMPONENT: + if (dimensions != 2) { + return GL_INVALID_OPERATION; + } + switch (type) { + case GL_UNSIGNED_SHORT: + if (internalFormat != GL_DEPTH_COMPONENT16) + return GL_INVALID_OPERATION; + break; + + case GL_UNSIGNED_INT: + switch (internalFormat) { + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + break; + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_FLOAT: + if (internalFormat != GL_DEPTH_COMPONENT32F) + return GL_INVALID_OPERATION; + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_DEPTH_STENCIL: + if (dimensions != 2) { + return GL_INVALID_OPERATION; + } + switch (type) { + case GL_UNSIGNED_INT_24_8: + if (internalFormat != GL_DEPTH24_STENCIL8) + return GL_INVALID_OPERATION; + break; + + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + if (internalFormat != GL_DEPTH32F_STENCIL8) + return GL_INVALID_OPERATION; + break; + + default: + return GL_INVALID_OPERATION; + } + break; + + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + if (type != GL_UNSIGNED_BYTE || format != internalFormat) + return GL_INVALID_OPERATION; + break; + } + + return type_valid ? GL_NO_ERROR : GL_INVALID_OPERATION; +} diff --git a/mesalib/src/mesa/main/glformats.h b/mesalib/src/mesa/main/glformats.h index fe604ddc9..4cbc82f5e 100644 --- a/mesalib/src/mesa/main/glformats.h +++ b/mesalib/src/mesa/main/glformats.h @@ -120,6 +120,11 @@ extern GLenum _mesa_es_error_check_format_and_type(GLenum format, GLenum type, unsigned dimensions); +extern GLenum +_mesa_es3_error_check_format_and_type(GLenum format, GLenum type, + GLenum internalFormat, + unsigned dimensions); + #ifdef __cplusplus } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 8904b13d9..d0c0e24ac 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2523,6 +2523,7 @@ struct gl_query_object GLuint64EXT Result; /**< the counter */ GLboolean Active; /**< inside Begin/EndQuery */ GLboolean Ready; /**< result is ready? */ + GLboolean EverBound;/**< has query object ever been bound */ }; @@ -3030,6 +3031,7 @@ struct gl_extensions GLboolean ARB_half_float_pixel; GLboolean ARB_half_float_vertex; GLboolean ARB_instanced_arrays; + GLboolean ARB_internalformat_query; GLboolean ARB_map_buffer_alignment; GLboolean ARB_map_buffer_range; GLboolean ARB_occlusion_query; diff --git a/mesalib/src/mesa/main/pack.c b/mesalib/src/mesa/main/pack.c index 4f0caa763..d6a97b35a 100644 --- a/mesalib/src/mesa/main/pack.c +++ b/mesalib/src/mesa/main/pack.c @@ -3641,7 +3641,11 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], rgba[i][rDst] = ((p ) & 0x3ff) * rs; rgba[i][gDst] = ((p >> 10) & 0x3ff) * gs; rgba[i][bDst] = ((p >> 20) & 0x3ff) * bs; - rgba[i][aDst] = ((p >> 30) ) * as; + if (aSrc < 0) { + rgba[i][aDst] = 1.0F; + } else { + rgba[i][aDst] = (p >> 30) * as; + } } } else { @@ -3652,7 +3656,11 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], rgba[i][rDst] = ((p ) & 0x3ff) * rs; rgba[i][gDst] = ((p >> 10) & 0x3ff) * gs; rgba[i][bDst] = ((p >> 20) & 0x3ff) * bs; - rgba[i][aDst] = ((p >> 30) ) * as; + if (aSrc < 0) { + rgba[i][aDst] = 1.0F; + } else { + rgba[i][aDst] = (p >> 30) * as; + } } } break; diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c index 054dfbad7..bd7d0d297 100644 --- a/mesalib/src/mesa/main/queryobj.c +++ b/mesalib/src/mesa/main/queryobj.c @@ -50,7 +50,20 @@ _mesa_new_query_object(struct gl_context *ctx, GLuint id) q->Id = id; q->Result = 0; q->Active = GL_FALSE; - q->Ready = GL_TRUE; /* correct, see spec */ + + /* This is to satisfy the language of the specification: "In the initial + * state of a query object, the result is available" (OpenGL 3.1 § + * 2.13). + */ + q->Ready = GL_TRUE; + + /* OpenGL 3.1 § 2.13 says about GenQueries, "These names are marked as + * used, but no object is associated with them until the first time they + * are used by BeginQuery." Since our implementation actually does + * allocate an object at this point, use a flag to indicate that this + * object has not yet been bound so should not be considered a query. + */ + q->EverBound = GL_FALSE; } return q; } @@ -252,16 +265,22 @@ _mesa_DeleteQueries(GLsizei n, const GLuint *ids) GLboolean GLAPIENTRY _mesa_IsQuery(GLuint id) { + struct gl_query_object *q; + GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glIsQuery(%u)\n", id); - if (id && _mesa_lookup_query_object(ctx, id)) - return GL_TRUE; - else + if (id == 0) return GL_FALSE; + + q = _mesa_lookup_query_object(ctx, id); + if (q == NULL) + return GL_FALSE; + + return q->EverBound; } static GLboolean @@ -354,6 +373,7 @@ _mesa_BeginQueryIndexed(GLenum target, GLuint index, GLuint id) q->Active = GL_TRUE; q->Result = 0; q->Ready = GL_FALSE; + q->EverBound = GL_TRUE; /* XXX should probably refcount query objects */ *bindpt = q; diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index d6d105bc4..5b80e9a8b 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -679,7 +679,7 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels ) { - GLenum err; + GLenum err = GL_NO_ERROR; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -707,17 +707,21 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, * preferred combination. This code doesn't know what that preferred * combination is, and Mesa can handle anything valid. Just work instead. */ - if (_mesa_is_gles(ctx) && ctx->Version < 30) { - err = _mesa_es_error_check_format_and_type(format, type, 2); - if (err == GL_NO_ERROR) { - if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) { - err = GL_INVALID_OPERATION; - } else if (format == GL_DEPTH_COMPONENT - || format == GL_DEPTH_STENCIL) { - err = GL_INVALID_ENUM; + if (_mesa_is_gles(ctx)) { + if (ctx->Version < 30) { + err = _mesa_es_error_check_format_and_type(format, type, 2); + if (err == GL_NO_ERROR) { + if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) { + err = GL_INVALID_OPERATION; + } } } + if (err == GL_NO_ERROR && (format == GL_DEPTH_COMPONENT + || format == GL_DEPTH_STENCIL)) { + err = GL_INVALID_ENUM; + } + if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", _mesa_lookup_enum_by_nr(format), diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 7d3abb7e0..5e451e235 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -1893,23 +1893,30 @@ texture_error_check( struct gl_context *ctx, * requires GL_OES_texture_float) are filtered elsewhere. */ - if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) { - if (format != internalFormat) { + if (_mesa_is_gles(ctx)) { + if (_mesa_is_gles3(ctx)) { + err = _mesa_es3_error_check_format_and_type(format, type, + internalFormat, + dimensions); + } else { + if (format != internalFormat) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexImage%dD(format = %s, internalFormat = %s)", dimensions, _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; - } + } - err = _mesa_es_error_check_format_and_type(format, type, dimensions); + err = _mesa_es_error_check_format_and_type(format, type, dimensions); + } if (err != GL_NO_ERROR) { _mesa_error(ctx, err, - "glTexImage%dD(format = %s, type = %s)", + "glTexImage%dD(format = %s, type = %s, internalFormat = %s)", dimensions, _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type)); + _mesa_lookup_enum_by_nr(type), + _mesa_lookup_enum_by_nr(internalFormat)); return GL_TRUE; } } @@ -2340,6 +2347,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, GLint width, GLint height, GLint border ) { GLint baseFormat; + struct gl_renderbuffer *rb; + GLenum rb_internal_format; /* check target */ if (!legal_texsubimage_target(ctx, dimensions, target)) { @@ -2384,6 +2393,13 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } + rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); + if (rb == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%dD(read buffer)", dimensions); + return GL_TRUE; + } + /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the * internalFormat. */ @@ -2409,6 +2425,8 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, return GL_TRUE; } + rb_internal_format = rb->InternalFormat; + if (!_mesa_source_buffer_exists(ctx, baseFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexImage%dD(missing readbuffer)", dimensions); @@ -2423,13 +2441,20 @@ copytexture_error_check( struct gl_context *ctx, GLuint dimensions, * integer format and the read color buffer is an integer format." */ if (_mesa_is_color_format(internalFormat)) { - struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; - - if (_mesa_is_enum_format_integer(rb->InternalFormat) != - _mesa_is_enum_format_integer(internalFormat)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyTexImage%dD(integer vs non-integer)", dimensions); - return GL_TRUE; + bool is_int = _mesa_is_enum_format_integer(internalFormat); + bool is_rbint = _mesa_is_enum_format_integer(rb_internal_format); + if (is_int || is_rbint) { + if (is_int != is_rbint) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%dD(integer vs non-integer)", dimensions); + return GL_TRUE; + } else if (_mesa_is_gles(ctx) && + _mesa_is_enum_format_unsigned_int(internalFormat) != + _mesa_is_enum_format_unsigned_int(rb_internal_format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%dD(signed vs unsigned integer)", dimensions); + return GL_TRUE; + } } } @@ -3340,9 +3365,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, border, internalFormat, texFormat); /* Allocate texture memory (no pixel data yet) */ - ctx->Driver.TexImage(ctx, dims, texImage, - GL_NONE, GL_NONE, - NULL, &ctx->Unpack); + ctx->Driver.AllocTextureImageBuffer(ctx, texImage); if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY, &width, &height)) { diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index ca5a21f78..4d32fd6dd 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -662,21 +662,16 @@ _mesa_TexParameterf(GLenum target, GLenum pname, GLfloat param) case GL_DEPTH_TEXTURE_MODE_ARB: case GL_TEXTURE_SRGB_DECODE_EXT: case GL_TEXTURE_CUBE_MAP_SEAMLESS: - { - /* convert float param to int */ - GLint p[4]; - p[0] = (GLint) param; - p[1] = p[2] = p[3] = 0; - need_update = set_tex_parameteri(ctx, texObj, pname, p); - } - break; case GL_TEXTURE_SWIZZLE_R_EXT: case GL_TEXTURE_SWIZZLE_G_EXT: case GL_TEXTURE_SWIZZLE_B_EXT: case GL_TEXTURE_SWIZZLE_A_EXT: { GLint p[4]; - p[0] = (GLint) param; + p[0] = (param > 0) ? + ((param > INT_MAX) ? INT_MAX : (GLint) (param + 0.5)) : + ((param < INT_MIN) ? INT_MIN : (GLint) (param - 0.5)); + p[1] = p[2] = p[3] = 0; need_update = set_tex_parameteri(ctx, texObj, pname, p); } diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index e453b3b0e..0f7e2a69b 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -151,21 +151,21 @@ update_array(struct gl_context *ctx, } if (_mesa_is_gles(ctx)) { - /* Once Mesa gets support for GL_OES_vertex_half_float this mask will - * change. Adding support for this extension isn't quite as trivial as - * we'd like because ES uses a different enum value for GL_HALF_FLOAT. - */ - legalTypesMask &= ~(FIXED_GL_BIT | HALF_BIT | DOUBLE_BIT); + legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT); /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or - * GL_OES_vertex_type_10_10_10_2. + * GL_OES_vertex_type_10_10_10_2. GL_HALF_FLOAT data is not allowed + * until 3.0 or with the GL_OES_vertex_half float extension, which isn't + * quite as trivial as we'd like because it uses a different enum value + * for GL_HALF_FLOAT_OES. */ if (ctx->Version < 30) { legalTypesMask &= ~(UNSIGNED_INT_BIT | INT_BIT | UNSIGNED_INT_2_10_10_10_REV_BIT - | INT_2_10_10_10_REV_BIT); + | INT_2_10_10_10_REV_BIT + | HALF_BIT); } /* BGRA ordering is not supported in ES contexts. diff --git a/mesalib/src/mesa/sources.mak b/mesalib/src/mesa/sources.mak index 8cde2c4cf..178ceb208 100644 --- a/mesalib/src/mesa/sources.mak +++ b/mesalib/src/mesa/sources.mak @@ -42,6 +42,7 @@ MAIN_FILES = \ $(SRCDIR)main/ffvertex_prog.c \ $(SRCDIR)main/ff_fragment_shader.cpp \ $(SRCDIR)main/fog.c \ + $(SRCDIR)main/formatquery.c \ $(SRCDIR)main/formats.c \ $(SRCDIR)main/format_pack.c \ $(SRCDIR)main/format_unpack.c \ diff --git a/mesalib/src/mesa/state_tracker/st_atom_shader.c b/mesalib/src/mesa/state_tracker/st_atom_shader.c index 45e7a117f..c1d7c80bb 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_shader.c +++ b/mesalib/src/mesa/state_tracker/st_atom_shader.c @@ -59,7 +59,8 @@ get_passthrough_fs(struct st_context *st) { if (!st->passthrough_fs) { st->passthrough_fs = - util_make_fragment_passthrough_shader(st->pipe); + util_make_fragment_passthrough_shader(st->pipe, TGSI_SEMANTIC_COLOR, + TGSI_INTERPOLATE_PERSPECTIVE); } return st->passthrough_fs; diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index 4aa0bc18f..d01236e28 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -65,13 +65,10 @@ void st_init_clear(struct st_context *st) { - struct pipe_screen *pscreen = st->pipe->screen; - memset(&st->clear, 0, sizeof(st->clear)); st->clear.raster.gl_rasterization_rules = 1; st->clear.raster.depth_clip = 1; - st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE); } @@ -99,7 +96,9 @@ static INLINE void set_fragment_shader(struct st_context *st) { if (!st->clear.fs) - st->clear.fs = util_make_fragment_passthrough_shader(st->pipe); + st->clear.fs = + util_make_fragment_passthrough_shader(st->pipe, TGSI_SEMANTIC_GENERIC, + TGSI_INTERPOLATE_CONSTANT); cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); } @@ -117,7 +116,7 @@ set_vertex_shader(struct st_context *st) if (!st->clear.vs) { const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, - TGSI_SEMANTIC_COLOR }; + TGSI_SEMANTIC_GENERIC }; const uint semantic_indexes[] = { 0, 0 }; st->clear.vs = util_make_vertex_passthrough_shader(st->pipe, 2, semantic_names, @@ -233,19 +232,24 @@ clear_with_quad(struct gl_context *ctx, { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; if (color) { - if (ctx->Color.ColorMask[0][0]) - blend.rt[0].colormask |= PIPE_MASK_R; - if (ctx->Color.ColorMask[0][1]) - blend.rt[0].colormask |= PIPE_MASK_G; - if (ctx->Color.ColorMask[0][2]) - blend.rt[0].colormask |= PIPE_MASK_B; - if (ctx->Color.ColorMask[0][3]) - blend.rt[0].colormask |= PIPE_MASK_A; + int num_buffers = ctx->Extensions.EXT_draw_buffers2 ? + ctx->DrawBuffer->_NumColorDrawBuffers : 1; + int i; + + blend.independent_blend_enable = num_buffers > 1; + + for (i = 0; i < num_buffers; i++) { + if (ctx->Color.ColorMask[i][0]) + blend.rt[i].colormask |= PIPE_MASK_R; + if (ctx->Color.ColorMask[i][1]) + blend.rt[i].colormask |= PIPE_MASK_G; + if (ctx->Color.ColorMask[i][2]) + blend.rt[i].colormask |= PIPE_MASK_B; + if (ctx->Color.ColorMask[i][3]) + blend.rt[i].colormask |= PIPE_MASK_A; + } + if (st->ctx->Color.DitherFlag) blend.dither = 1; } @@ -333,113 +337,42 @@ clear_with_quad(struct gl_context *ctx, /** - * Determine if we need to clear the depth buffer by drawing a quad. - */ -static INLINE GLboolean -check_clear_color_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb) -{ - if (ctx->Scissor.Enabled && - (ctx->Scissor.X != 0 || - ctx->Scissor.Y != 0 || - ctx->Scissor.Width < rb->Width || - ctx->Scissor.Height < rb->Height)) - return GL_TRUE; - - if (!ctx->Color.ColorMask[0][0] || - !ctx->Color.ColorMask[0][1] || - !ctx->Color.ColorMask[0][2] || - !ctx->Color.ColorMask[0][3]) - return GL_TRUE; - - return GL_FALSE; -} - - -/** - * Determine if we need to clear the combiend depth/stencil buffer by - * drawing a quad. + * Return if the scissor must be enabled during the clear. */ static INLINE GLboolean -check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb) +is_scissor_enabled(struct gl_context *ctx, struct gl_renderbuffer *rb) { - const GLuint stencilMax = 0xff; - GLboolean maskStencil - = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax; - - assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0); - - if (ctx->Scissor.Enabled && - (ctx->Scissor.X != 0 || - ctx->Scissor.Y != 0 || - ctx->Scissor.Width < rb->Width || - ctx->Scissor.Height < rb->Height)) - return GL_TRUE; - - if (maskStencil) - return GL_TRUE; - - return GL_FALSE; + return ctx->Scissor.Enabled && + (ctx->Scissor.X > 0 || + ctx->Scissor.Y > 0 || + ctx->Scissor.Width < rb->Width || + ctx->Scissor.Height < rb->Height); } /** - * Determine if we need to clear the depth buffer by drawing a quad. + * Return if any of the color channels are masked. */ static INLINE GLboolean -check_clear_depth_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb, - boolean ds_separate) +is_color_masked(struct gl_context *ctx, int i) { - const struct st_renderbuffer *strb = st_renderbuffer(rb); - const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format); - - if (ctx->Scissor.Enabled && - (ctx->Scissor.X != 0 || - ctx->Scissor.Y != 0 || - ctx->Scissor.Width < rb->Width || - ctx->Scissor.Height < rb->Height)) - return GL_TRUE; - - if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0) - return GL_TRUE; - - return GL_FALSE; + return !ctx->Color.ColorMask[i][0] || + !ctx->Color.ColorMask[i][1] || + !ctx->Color.ColorMask[i][2] || + !ctx->Color.ColorMask[i][3]; } /** - * Determine if we need to clear the stencil buffer by drawing a quad. + * Return if any of the stencil bits are masked. */ static INLINE GLboolean -check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb, - boolean ds_separate) +is_stencil_masked(struct gl_context *ctx, struct gl_renderbuffer *rb) { - const struct st_renderbuffer *strb = st_renderbuffer(rb); - const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format); const GLuint stencilMax = 0xff; - const GLboolean maskStencil - = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax; assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0); - - if (maskStencil) - return GL_TRUE; - - if (ctx->Scissor.Enabled && - (ctx->Scissor.X != 0 || - ctx->Scissor.Y != 0 || - ctx->Scissor.Width < rb->Width || - ctx->Scissor.Height < rb->Height)) - return GL_TRUE; - - /* This is correct, but it is necessary to look at the depth clear - * value held in the surface when it comes time to issue the clear, - * rather than taking depth and stencil clear values from the - * current state. - */ - if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0) - return GL_TRUE; - - return GL_FALSE; + return (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax; } @@ -449,8 +382,6 @@ check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb static void st_Clear(struct gl_context *ctx, GLbitfield mask) { - static const GLbitfield BUFFER_BITS_DS - = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); struct st_context *st = st_context(ctx); struct gl_renderbuffer *depthRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; @@ -471,11 +402,13 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[b].Renderbuffer; struct st_renderbuffer *strb = st_renderbuffer(rb); + int colormask_index = ctx->Extensions.EXT_draw_buffers2 ? i : 0; if (!strb || !strb->surface) continue; - if (check_clear_color_with_quad( ctx, rb )) + if (is_scissor_enabled(ctx, rb) || + is_color_masked(ctx, colormask_index)) quad_buffers |= PIPE_CLEAR_COLOR; else clear_buffers |= PIPE_CLEAR_COLOR; @@ -483,41 +416,25 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) } } - if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) { - /* clearing combined depth + stencil */ + if (mask & BUFFER_BIT_DEPTH) { struct st_renderbuffer *strb = st_renderbuffer(depthRb); if (strb->surface) { - if (check_clear_depth_stencil_with_quad(ctx, depthRb)) - quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + if (is_scissor_enabled(ctx, depthRb)) + quad_buffers |= PIPE_CLEAR_DEPTH; else - clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + clear_buffers |= PIPE_CLEAR_DEPTH; } } - else { - /* separate depth/stencil clears */ - /* I don't think truly separate buffers are actually possible in gallium or hw? */ - if (mask & BUFFER_BIT_DEPTH) { - struct st_renderbuffer *strb = st_renderbuffer(depthRb); - - if (strb->surface) { - if (check_clear_depth_with_quad(ctx, depthRb, - st->clear.enable_ds_separate)) - quad_buffers |= PIPE_CLEAR_DEPTH; - else - clear_buffers |= PIPE_CLEAR_DEPTH; - } - } - if (mask & BUFFER_BIT_STENCIL) { - struct st_renderbuffer *strb = st_renderbuffer(stencilRb); + if (mask & BUFFER_BIT_STENCIL) { + struct st_renderbuffer *strb = st_renderbuffer(stencilRb); - if (strb->surface) { - if (check_clear_stencil_with_quad(ctx, stencilRb, - st->clear.enable_ds_separate)) - quad_buffers |= PIPE_CLEAR_STENCIL; - else - clear_buffers |= PIPE_CLEAR_STENCIL; - } + if (strb->surface) { + if (is_scissor_enabled(ctx, stencilRb) || + is_stencil_masked(ctx, stencilRb)) + quad_buffers |= PIPE_CLEAR_STENCIL; + else + clear_buffers |= PIPE_CLEAR_STENCIL; } } @@ -532,20 +449,8 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) quad_buffers & PIPE_CLEAR_DEPTH, quad_buffers & PIPE_CLEAR_STENCIL); } else if (clear_buffers) { - /* driver cannot know it can clear everything if the buffer - * is a combined depth/stencil buffer but this wasn't actually - * required from the visual. Hence fix this up to avoid potential - * read-modify-write in the driver. - */ union pipe_color_union clearColor; - if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) && - ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && - (depthRb == stencilRb) && - (ctx->DrawBuffer->Visual.depthBits == 0 || - ctx->DrawBuffer->Visual.stencilBits == 0)) - clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; - if (ctx->DrawBuffer->_ColorDrawBuffers[0]) { struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; GLboolean is_integer = _mesa_is_enum_format_integer(rb->InternalFormat); diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index bf206b025..d042ebabf 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -317,9 +317,11 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) break; case PIPE_FORMAT_Z24_UNORM_S8_UINT: case PIPE_FORMAT_S8_UINT_Z24_UNORM: + strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; + break; case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_X8Z24_UNORM: - strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; + strb->Base.InternalFormat = GL_DEPTH_COMPONENT24; break; case PIPE_FORMAT_S8_UINT: strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index 2be74b452..70ee671d0 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -172,7 +172,6 @@ struct st_context struct pipe_viewport_state viewport; void *vs; void *fs; - boolean enable_ds_separate; } clear; /** used for anything using util_draw_vertex_buffer */ diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index b0c56a40f..043b578a5 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -111,6 +111,11 @@ blit_nearest(struct gl_context *ctx, GLbitfield buffer) { struct gl_renderbuffer *readRb, *drawRb; + struct gl_renderbuffer_attachment *readAtt, *drawAtt; + struct gl_framebuffer *readFb = ctx->ReadBuffer; + struct gl_framebuffer *drawFb = ctx->DrawBuffer; + GLint NumDrawBuffers = 0; + GLuint i; const GLint srcWidth = ABS(srcX1 - srcX0); const GLint dstWidth = ABS(dstX1 - dstX0); @@ -146,21 +151,16 @@ blit_nearest(struct gl_context *ctx, switch (buffer) { case GL_COLOR_BUFFER_BIT: - readRb = ctx->ReadBuffer->_ColorReadBuffer; - drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; - - if (readRb->Format == drawRb->Format) { - mode = DIRECT; - pixelSize = _mesa_get_format_bytes(readRb->Format); - } else { - mode = UNPACK_RGBA_FLOAT; - pixelSize = 16; - } - + readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex]; + readRb = readFb->_ColorReadBuffer; + NumDrawBuffers = drawFb->_NumColorDrawBuffers; break; case GL_DEPTH_BUFFER_BIT: - readRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; - drawRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; + readAtt = &readFb->Attachment[BUFFER_DEPTH]; + drawAtt = &drawFb->Attachment[BUFFER_DEPTH]; + readRb = readAtt->Renderbuffer; + drawRb = drawAtt->Renderbuffer; + NumDrawBuffers = 1; /* Note that for depth/stencil, the formats of src/dst must match. By * using the core helpers for pack/unpack, we avoid needing to handle @@ -175,8 +175,11 @@ blit_nearest(struct gl_context *ctx, pixelSize = 4; break; case GL_STENCIL_BUFFER_BIT: - readRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; - drawRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; + readAtt = &readFb->Attachment[BUFFER_STENCIL]; + drawAtt = &drawFb->Attachment[BUFFER_STENCIL]; + readRb = readAtt->Renderbuffer; + drawRb = drawAtt->Renderbuffer; + NumDrawBuffers = 1; mode = UNPACK_S; pixelSize = 1; break; @@ -208,146 +211,167 @@ blit_nearest(struct gl_context *ctx, return; } - if (readRb == drawRb) { - /* map whole buffer for read/write */ - /* XXX we could be clever and just map the union region of the - * source and dest rects. - */ - GLubyte *map; - GLint rowStride; - GLint formatSize = _mesa_get_format_bytes(readRb->Format); - - ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0, - readRb->Width, readRb->Height, - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, - &map, &rowStride); - if (!map) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + /* Blit to all the draw buffers */ + for (i = 0; i < NumDrawBuffers; i++) { + if (buffer == GL_COLOR_BUFFER_BIT) { + int idx = drawFb->_ColorDrawBufferIndexes[i]; + if (idx == -1) + continue; + drawAtt = &drawFb->Attachment[idx]; + drawRb = drawAtt->Renderbuffer; + + if (readRb->Format == drawRb->Format) { + mode = DIRECT; + pixelSize = _mesa_get_format_bytes(readRb->Format); + } else { + mode = UNPACK_RGBA_FLOAT; + pixelSize = 16; + } } - srcMap = map + srcYpos * rowStride + srcXpos * formatSize; - dstMap = map + dstYpos * rowStride + dstXpos * formatSize; + if ((readRb == drawRb) || + (readAtt->Texture && drawAtt->Texture && + (readAtt->Texture == drawAtt->Texture))) { + /* map whole buffer for read/write */ + /* XXX we could be clever and just map the union region of the + * source and dest rects. + */ + GLubyte *map; + GLint rowStride; + GLint formatSize = _mesa_get_format_bytes(readRb->Format); + + ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0, + readRb->Width, readRb->Height, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, + &map, &rowStride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + return; + } + + srcMap = map + srcYpos * rowStride + srcXpos * formatSize; + dstMap = map + dstYpos * rowStride + dstXpos * formatSize; - /* this handles overlapping copies */ - if (srcY0 < dstY0) { - /* copy in reverse (top->down) order */ - srcMap += rowStride * (readRb->Height - 1); - dstMap += rowStride * (readRb->Height - 1); - srcRowStride = -rowStride; - dstRowStride = -rowStride; + /* this handles overlapping copies */ + if (srcY0 < dstY0) { + /* copy in reverse (top->down) order */ + srcMap += rowStride * (readRb->Height - 1); + dstMap += rowStride * (readRb->Height - 1); + srcRowStride = -rowStride; + dstRowStride = -rowStride; + } + else { + /* copy in normal (bottom->up) order */ + srcRowStride = rowStride; + dstRowStride = rowStride; + } } else { - /* copy in normal (bottom->up) order */ - srcRowStride = rowStride; - dstRowStride = rowStride; + /* different src/dst buffers */ + ctx->Driver.MapRenderbuffer(ctx, readRb, + srcXpos, srcYpos, + srcWidth, srcHeight, + GL_MAP_READ_BIT, &srcMap, &srcRowStride); + if (!srcMap) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + return; + } + ctx->Driver.MapRenderbuffer(ctx, drawRb, + dstXpos, dstYpos, + dstWidth, dstHeight, + GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); + if (!dstMap) { + ctx->Driver.UnmapRenderbuffer(ctx, readRb); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + return; + } } - } - else { - /* different src/dst buffers */ - ctx->Driver.MapRenderbuffer(ctx, readRb, - srcXpos, srcYpos, - srcWidth, srcHeight, - GL_MAP_READ_BIT, &srcMap, &srcRowStride); - if (!srcMap) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + + /* allocate the src/dst row buffers */ + srcBuffer = malloc(pixelSize * srcWidth); + if (!srcBuffer) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } - ctx->Driver.MapRenderbuffer(ctx, drawRb, - dstXpos, dstYpos, - dstWidth, dstHeight, - GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); - if (!dstMap) { - ctx->Driver.UnmapRenderbuffer(ctx, readRb); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + dstBuffer = malloc(pixelSize * dstWidth); + if (!dstBuffer) { + free(srcBuffer); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); return; } - } - /* allocate the src/dst row buffers */ - srcBuffer = malloc(pixelSize * srcWidth); - if (!srcBuffer) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; - } - dstBuffer = malloc(pixelSize * dstWidth); - if (!dstBuffer) { - free(srcBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; - } - - for (dstRow = 0; dstRow < dstHeight; dstRow++) { - GLint srcRow = (dstRow * srcHeight) / dstHeight; - GLubyte *dstRowStart = dstMap + dstRowStride * dstRow; + for (dstRow = 0; dstRow < dstHeight; dstRow++) { + GLint srcRow = (dstRow * srcHeight) / dstHeight; + GLubyte *dstRowStart = dstMap + dstRowStride * dstRow; - ASSERT(srcRow >= 0); - ASSERT(srcRow < srcHeight); + ASSERT(srcRow >= 0); + ASSERT(srcRow < srcHeight); - if (invertY) { - srcRow = srcHeight - 1 - srcRow; - } + if (invertY) { + srcRow = srcHeight - 1 - srcRow; + } - /* get pixel row from source and resample to match dest width */ - if (prevY != srcRow) { - GLubyte *srcRowStart = srcMap + srcRowStride * srcRow; - - switch (mode) { - case DIRECT: - memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth); - break; - case UNPACK_RGBA_FLOAT: - _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart, - srcBuffer); - break; - case UNPACK_Z_FLOAT: - _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart, - srcBuffer); - break; - case UNPACK_Z_INT: - _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart, - srcBuffer); - break; - case UNPACK_S: - _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth, - srcRowStart, srcBuffer); - break; - } + /* get pixel row from source and resample to match dest width */ + if (prevY != srcRow) { + GLubyte *srcRowStart = srcMap + srcRowStride * srcRow; + + switch (mode) { + case DIRECT: + memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth); + break; + case UNPACK_RGBA_FLOAT: + _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart, + srcBuffer); + break; + case UNPACK_Z_FLOAT: + _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart, + srcBuffer); + break; + case UNPACK_Z_INT: + _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart, + srcBuffer); + break; + case UNPACK_S: + _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth, + srcRowStart, srcBuffer); + break; + } - (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX); - prevY = srcRow; - } + (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX); + prevY = srcRow; + } - /* store pixel row in destination */ - switch (mode) { - case DIRECT: - memcpy(dstRowStart, dstBuffer, pixelSize * srcWidth); - break; - case UNPACK_RGBA_FLOAT: - _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer, - dstRowStart); - break; - case UNPACK_Z_FLOAT: - _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer, - dstRowStart); - break; - case UNPACK_Z_INT: - _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer, - dstRowStart); - break; - case UNPACK_S: - _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer, - dstRowStart); - break; + /* store pixel row in destination */ + switch (mode) { + case DIRECT: + memcpy(dstRowStart, dstBuffer, pixelSize * srcWidth); + break; + case UNPACK_RGBA_FLOAT: + _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer, + dstRowStart); + break; + case UNPACK_Z_FLOAT: + _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer, + dstRowStart); + break; + case UNPACK_Z_INT: + _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer, + dstRowStart); + break; + case UNPACK_S: + _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer, + dstRowStart); + break; + } } - } - free(srcBuffer); - free(dstBuffer); + free(srcBuffer); + free(dstBuffer); - ctx->Driver.UnmapRenderbuffer(ctx, readRb); - if (drawRb != readRb) { - ctx->Driver.UnmapRenderbuffer(ctx, drawRb); + ctx->Driver.UnmapRenderbuffer(ctx, readRb); + if (drawRb != readRb) { + ctx->Driver.UnmapRenderbuffer(ctx, drawRb); + } } } @@ -489,8 +513,13 @@ blit_linear(struct gl_context *ctx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) { - struct gl_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer; - struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0]; + struct gl_framebuffer *drawFb = ctx->DrawBuffer; + struct gl_renderbuffer *drawRb = NULL; + struct gl_renderbuffer_attachment *drawAtt = NULL; + struct gl_framebuffer *readFb = ctx->ReadBuffer; + struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer; + struct gl_renderbuffer_attachment *readAtt = + &readFb->Attachment[readFb->_ColorReadBufferIndex]; const GLint srcWidth = ABS(srcX1 - srcX0); const GLint dstWidth = ABS(dstX1 - dstX0); @@ -521,6 +550,7 @@ blit_linear(struct gl_context *ctx, GLubyte *srcMap, *dstMap; GLint srcRowStride, dstRowStride; + GLuint i; /* Determine datatype for resampling */ @@ -556,151 +586,160 @@ blit_linear(struct gl_context *ctx, return; } - /* - * Map src / dst renderbuffers - */ - if (readRb == drawRb) { - /* map whole buffer for read/write */ - ctx->Driver.MapRenderbuffer(ctx, readRb, - 0, 0, readRb->Width, readRb->Height, - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, - &srcMap, &srcRowStride); - if (!srcMap) { - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; - } - - dstMap = srcMap; - dstRowStride = srcRowStride; - } - else { - /* different src/dst buffers */ - /* XXX with a bit of work we could just map the regions to be - * read/written instead of the whole buffers. + for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) { + int idx = drawFb->_ColorDrawBufferIndexes[i]; + if (idx == -1) + continue; + drawAtt = &drawFb->Attachment[idx]; + drawRb = drawAtt->Renderbuffer; + /* + * Map src / dst renderbuffers */ - ctx->Driver.MapRenderbuffer(ctx, readRb, - 0, 0, readRb->Width, readRb->Height, - GL_MAP_READ_BIT, &srcMap, &srcRowStride); - if (!srcMap) { - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + if ((readRb == drawRb) || + (readAtt->Texture && drawAtt->Texture && + (readAtt->Texture = drawAtt->Texture))) { + /* map whole buffer for read/write */ + ctx->Driver.MapRenderbuffer(ctx, readRb, + 0, 0, readRb->Width, readRb->Height, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, + &srcMap, &srcRowStride); + if (!srcMap) { + free(srcBuffer0); + free(srcBuffer1); + free(dstBuffer); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + return; + } + + dstMap = srcMap; + dstRowStride = srcRowStride; } - ctx->Driver.MapRenderbuffer(ctx, drawRb, - 0, 0, drawRb->Width, drawRb->Height, - GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); - if (!dstMap) { - ctx->Driver.UnmapRenderbuffer(ctx, readRb); - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + else { + /* different src/dst buffers */ + /* XXX with a bit of work we could just map the regions to be + * read/written instead of the whole buffers. + */ + ctx->Driver.MapRenderbuffer(ctx, readRb, + 0, 0, readRb->Width, readRb->Height, + GL_MAP_READ_BIT, &srcMap, &srcRowStride); + if (!srcMap) { + free(srcBuffer0); + free(srcBuffer1); + free(dstBuffer); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + return; + } + ctx->Driver.MapRenderbuffer(ctx, drawRb, + 0, 0, drawRb->Width, drawRb->Height, + GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); + if (!dstMap) { + ctx->Driver.UnmapRenderbuffer(ctx, readRb); + free(srcBuffer0); + free(srcBuffer1); + free(dstBuffer); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); + return; + } } - } - for (dstRow = 0; dstRow < dstHeight; dstRow++) { - const GLint dstY = dstYpos + dstRow; - const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF; - GLint srcRow0 = IFLOOR(srcRow); - GLint srcRow1 = srcRow0 + 1; - GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */ + for (dstRow = 0; dstRow < dstHeight; dstRow++) { + const GLint dstY = dstYpos + dstRow; + const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF; + GLint srcRow0 = IFLOOR(srcRow); + GLint srcRow1 = srcRow0 + 1; + GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */ - ASSERT(srcRow >= 0); - ASSERT(srcRow < srcHeight); + ASSERT(srcRow >= 0); + ASSERT(srcRow < srcHeight); - if (srcRow1 == srcHeight) { - /* last row fudge */ - srcRow1 = srcRow0; - rowWeight = 0.0; - } + if (srcRow1 == srcHeight) { + /* last row fudge */ + srcRow1 = srcRow0; + rowWeight = 0.0; + } - if (invertY) { - srcRow0 = srcHeight - 1 - srcRow0; - srcRow1 = srcHeight - 1 - srcRow1; - } + if (invertY) { + srcRow0 = srcHeight - 1 - srcRow0; + srcRow1 = srcHeight - 1 - srcRow1; + } - srcY0 = srcYpos + srcRow0; - srcY1 = srcYpos + srcRow1; + srcY0 = srcYpos + srcRow0; + srcY1 = srcYpos + srcRow1; - /* get the two source rows */ - if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) { - /* use same source row buffers again */ - } - else if (srcY0 == srcBufferY1) { - /* move buffer1 into buffer0 by swapping pointers */ - GLvoid *tmp = srcBuffer0; - srcBuffer0 = srcBuffer1; - srcBuffer1 = tmp; - /* get y1 row */ - { - GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp; - if (pixelType == GL_UNSIGNED_BYTE) { - _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, - src, srcBuffer1); + /* get the two source rows */ + if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) { + /* use same source row buffers again */ + } + else if (srcY0 == srcBufferY1) { + /* move buffer1 into buffer0 by swapping pointers */ + GLvoid *tmp = srcBuffer0; + srcBuffer0 = srcBuffer1; + srcBuffer1 = tmp; + /* get y1 row */ + { + GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp; + if (pixelType == GL_UNSIGNED_BYTE) { + _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, + src, srcBuffer1); + } + else { + _mesa_unpack_rgba_row(readFormat, srcWidth, + src, srcBuffer1); + } } - else { - _mesa_unpack_rgba_row(readFormat, srcWidth, - src, srcBuffer1); + srcBufferY0 = srcY0; + srcBufferY1 = srcY1; + } + else { + /* get both new rows */ + { + GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp; + GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp; + if (pixelType == GL_UNSIGNED_BYTE) { + _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, + src0, srcBuffer0); + _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, + src1, srcBuffer1); + } + else { + _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0); + _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1); + } } - } - srcBufferY0 = srcY0; - srcBufferY1 = srcY1; - } - else { - /* get both new rows */ + srcBufferY0 = srcY0; + srcBufferY1 = srcY1; + } + + if (pixelType == GL_UNSIGNED_BYTE) { + resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1, + dstBuffer, invertX, rowWeight); + } + else { + resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1, + dstBuffer, invertX, rowWeight); + } + + /* store pixel row in destination */ { - GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp; - GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp; + GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp; if (pixelType == GL_UNSIGNED_BYTE) { - _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, - src0, srcBuffer0); - _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth, - src1, srcBuffer1); + _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst); } else { - _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0); - _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1); + _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst); } } - srcBufferY0 = srcY0; - srcBufferY1 = srcY1; } - if (pixelType == GL_UNSIGNED_BYTE) { - resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1, - dstBuffer, invertX, rowWeight); - } - else { - resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1, - dstBuffer, invertX, rowWeight); - } + free(srcBuffer0); + free(srcBuffer1); + free(dstBuffer); - /* store pixel row in destination */ - { - GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp; - if (pixelType == GL_UNSIGNED_BYTE) { - _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst); - } - else { - _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst); - } + ctx->Driver.UnmapRenderbuffer(ctx, readRb); + if (drawRb != readRb) { + ctx->Driver.UnmapRenderbuffer(ctx, drawRb); } } - - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - - ctx->Driver.UnmapRenderbuffer(ctx, readRb); - if (drawRb != readRb) { - ctx->Driver.UnmapRenderbuffer(ctx, drawRb); - } } |