diff options
Diffstat (limited to 'mesalib/src/mesa/main/buffers.c')
-rw-r--r-- | mesalib/src/mesa/main/buffers.c | 101 |
1 files changed, 94 insertions, 7 deletions
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; } |