blob: 24b5c31050a97034987c704a244895c276319902 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// FramebufferGL.cpp: Implements the class methods for FramebufferGL.
8
9#include "libANGLE/renderer/gl/FramebufferGL.h"
10
Jamie Madill60ec6ea2016-01-22 15:27:19 -050011#include "common/BitSetIterator.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Jamie Madill9082b982016-04-27 15:21:51 -040013#include "libANGLE/ContextState.h"
Jamie Madill87de3622015-03-16 10:41:44 -040014#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040015#include "libANGLE/FramebufferAttachment.h"
16#include "libANGLE/angletypes.h"
17#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040018#include "libANGLE/renderer/ContextImpl.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040019#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020020#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040021#include "libANGLE/renderer/gl/StateManagerGL.h"
22#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langafd7f0a2015-09-09 15:33:31 -040023#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Geoff Langf607c602016-09-21 11:46:48 -040024#include "libANGLE/renderer/gl/formatutilsgl.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050025#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050026
Jamie Madill60ec6ea2016-01-22 15:27:19 -050027using namespace gl;
Corentin Wallez9a8d3662016-09-22 12:18:29 -040028using angle::CheckedNumeric;
Jamie Madill60ec6ea2016-01-22 15:27:19 -050029
Geoff Langf9a6f082015-01-22 13:32:49 -050030namespace rx
31{
32
Corentin Wallez9a8d3662016-09-22 12:18:29 -040033namespace
34{
35gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Rectangle &area,
36 const gl::PixelPackState &pack,
37 GLenum format,
38 GLenum type,
39 const void *pixels)
40{
41 if (pack.pixelBuffer.get() == nullptr)
42 {
43 return false;
44 }
45
46 // We are using an pack buffer, compute what the driver thinks is going to be the last
47 // byte written. If it is past the end of the buffer, we will need to use the workaround
48 // otherwise the driver will generate INVALID_OPERATION.
49 CheckedNumeric<size_t> checkedEndByte;
50 CheckedNumeric<size_t> pixelBytes;
51 size_t rowPitch;
52
53 gl::Extents size(area.width, area.height, 1);
54 const gl::InternalFormat &glFormat =
55 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
56 ANGLE_TRY_RESULT(glFormat.computePackEndByte(type, size, pack), checkedEndByte);
57 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
58 rowPitch);
59 pixelBytes = glFormat.computePixelBytes(type);
60
61 checkedEndByte += reinterpret_cast<intptr_t>(pixels);
62
63 // At this point checkedEndByte is the actual last byte written.
64 // The driver adds an extra row padding (if any), mimic it.
65 ANGLE_TRY_CHECKED_MATH(pixelBytes);
66 if (pixelBytes.ValueOrDie() * size.width < rowPitch)
67 {
68 checkedEndByte += rowPitch - pixelBytes * size.width;
69 }
70
71 ANGLE_TRY_CHECKED_MATH(checkedEndByte);
72
73 return checkedEndByte.ValueOrDie() > static_cast<size_t>(pack.pixelBuffer->getSize());
74}
75} // anonymous namespace
76
Jamie Madill48ef11b2016-04-27 15:21:52 -040077FramebufferGL::FramebufferGL(const FramebufferState &state,
Geoff Langafd7f0a2015-09-09 15:33:31 -040078 const FunctionsGL *functions,
79 StateManagerGL *stateManager,
80 const WorkaroundsGL &workarounds,
81 bool isDefault)
Jamie Madill48ef11b2016-04-27 15:21:52 -040082 : FramebufferImpl(state),
Geoff Lang4ad17092015-03-10 16:47:44 -040083 mFunctions(functions),
84 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040085 mWorkarounds(workarounds),
Corentin Wallez6ab01b92015-08-03 10:16:36 -070086 mFramebufferID(0),
87 mIsDefault(isDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040088{
Corentin Wallez6ab01b92015-08-03 10:16:36 -070089 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040090 {
91 mFunctions->genFramebuffers(1, &mFramebufferID);
92 }
93}
Geoff Langf9a6f082015-01-22 13:32:49 -050094
Corentin Wallez86f8dd72015-08-12 12:37:48 -070095FramebufferGL::FramebufferGL(GLuint id,
Jamie Madill48ef11b2016-04-27 15:21:52 -040096 const FramebufferState &state,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070097 const FunctionsGL *functions,
Geoff Langafd7f0a2015-09-09 15:33:31 -040098 const WorkaroundsGL &workarounds,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070099 StateManagerGL *stateManager)
Jamie Madill48ef11b2016-04-27 15:21:52 -0400100 : FramebufferImpl(state),
Corentin Wallez86f8dd72015-08-12 12:37:48 -0700101 mFunctions(functions),
102 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -0400103 mWorkarounds(workarounds),
Corentin Wallez86f8dd72015-08-12 12:37:48 -0700104 mFramebufferID(id),
105 mIsDefault(true)
106{
107}
108
Geoff Langf9a6f082015-01-22 13:32:49 -0500109FramebufferGL::~FramebufferGL()
Geoff Lang4ad17092015-03-10 16:47:44 -0400110{
Geoff Lang1eb708e2015-05-04 14:58:23 -0400111 mStateManager->deleteFramebuffer(mFramebufferID);
112 mFramebufferID = 0;
Geoff Lang4ad17092015-03-10 16:47:44 -0400113}
114
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500115static void BindFramebufferAttachment(const FunctionsGL *functions,
116 GLenum attachmentPoint,
117 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -0400118{
119 if (attachment)
120 {
121 if (attachment->type() == GL_TEXTURE)
122 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500123 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -0400124 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
125
126 if (texture->getTarget() == GL_TEXTURE_2D)
127 {
128 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
129 textureGL->getTextureID(), attachment->mipLevel());
130 }
131 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
132 {
133 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
134 textureGL->getTextureID(), attachment->mipLevel());
135 }
136 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
137 {
138 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
139 attachment->mipLevel(), attachment->layer());
140 }
141 else
142 {
143 UNREACHABLE();
144 }
145 }
146 else if (attachment->type() == GL_RENDERBUFFER)
147 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500148 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -0400149 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400150
Geoff Langcd69f1c2015-03-18 14:33:23 -0400151 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
152 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400153 }
154 else
155 {
156 UNREACHABLE();
157 }
158 }
159 else
160 {
161 // Unbind this attachment
162 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
163 }
164}
Geoff Langf9a6f082015-01-22 13:32:49 -0500165
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500166Error FramebufferGL::discard(size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700167{
168 UNIMPLEMENTED();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500169 return Error(GL_INVALID_OPERATION);
Austin Kinross08332632015-05-05 13:35:47 -0700170}
171
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500172Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500173{
Geoff Lang64a72442015-04-01 14:43:11 -0400174 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
175 if (mFunctions->invalidateFramebuffer)
176 {
177 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700178 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), attachments);
Geoff Lang64a72442015-04-01 14:43:11 -0400179 }
180
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500181 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500182}
183
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500184Error FramebufferGL::invalidateSub(size_t count,
185 const GLenum *attachments,
186 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500187{
Geoff Lang64a72442015-04-01 14:43:11 -0400188 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
189 if (mFunctions->invalidateSubFramebuffer)
190 {
191 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700192 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
193 attachments, area.x, area.y, area.width, area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400194 }
195
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500196 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500197}
198
Jamie Madill8415b5f2016-04-26 13:41:39 -0400199Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500200{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400201 syncClearState(mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400202 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
203 mFunctions->clear(mask);
204
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500205 return Error(GL_NO_ERROR);
Geoff Lang4ad17092015-03-10 16:47:44 -0400206}
207
Jamie Madill8415b5f2016-04-26 13:41:39 -0400208Error FramebufferGL::clearBufferfv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500209 GLenum buffer,
210 GLint drawbuffer,
211 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500212{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400213 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400214 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
215 mFunctions->clearBufferfv(buffer, drawbuffer, values);
216
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500217 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500218}
219
Jamie Madill8415b5f2016-04-26 13:41:39 -0400220Error FramebufferGL::clearBufferuiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500221 GLenum buffer,
222 GLint drawbuffer,
223 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500224{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400225 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400226 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
227 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
228
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500229 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500230}
231
Jamie Madill8415b5f2016-04-26 13:41:39 -0400232Error FramebufferGL::clearBufferiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500233 GLenum buffer,
234 GLint drawbuffer,
235 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500236{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400237 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400238 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
239 mFunctions->clearBufferiv(buffer, drawbuffer, values);
240
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500241 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500242}
243
Jamie Madill8415b5f2016-04-26 13:41:39 -0400244Error FramebufferGL::clearBufferfi(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500245 GLenum buffer,
246 GLint drawbuffer,
247 GLfloat depth,
248 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500249{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400250 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400251 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
252 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
253
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500254 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500255}
256
257GLenum FramebufferGL::getImplementationColorReadFormat() const
258{
Jamie Madilla3944d42016-07-22 22:13:26 -0400259 const auto *readAttachment = mState.getReadAttachment();
260 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400261 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500262}
263
264GLenum FramebufferGL::getImplementationColorReadType() const
265{
Jamie Madilla3944d42016-07-22 22:13:26 -0400266 const auto *readAttachment = mState.getReadAttachment();
267 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400268 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500269}
270
Jamie Madill8415b5f2016-04-26 13:41:39 -0400271Error FramebufferGL::readPixels(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500272 const gl::Rectangle &area,
273 GLenum format,
274 GLenum type,
275 GLvoid *pixels) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500276{
Geoff Langda34d002015-09-04 11:08:59 -0400277 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
278 // binding
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700279 const PixelPackState &packState = context->getGLState().getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400280 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400281
Geoff Langf607c602016-09-21 11:46:48 -0400282 nativegl::ReadPixelsFormat readPixelsFormat =
283 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400284 GLenum readFormat = readPixelsFormat.format;
285 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400286
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400287 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
288
289 if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
290 packState.rowLength != 0 && packState.rowLength < area.width)
291 {
292 return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
293 }
294
295 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
296 {
297 bool apply;
298 ANGLE_TRY_RESULT(
299 ShouldApplyLastRowPaddingWorkaround(area, packState, readFormat, readType, pixels),
300 apply);
301
302 if (apply)
303 {
304 return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
305 }
306 }
307
308 mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
309
310 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500311}
312
Jamie Madill8415b5f2016-04-26 13:41:39 -0400313Error FramebufferGL::blit(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500314 const gl::Rectangle &sourceArea,
315 const gl::Rectangle &destArea,
316 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400317 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500318{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700319 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400320 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
321
322 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
323 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
324
Jamie Madill2da819e2015-12-03 15:53:19 -0500325 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
326 destArea.x, destArea.y, destArea.x1(), destArea.y1(), mask, filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400327
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500328 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500329}
330
Jamie Madillcc86d642015-11-24 13:00:07 -0500331bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500332{
Geoff Lang4ad17092015-03-10 16:47:44 -0400333 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500334 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
335 if (status != GL_FRAMEBUFFER_COMPLETE)
336 {
337 ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
338 }
339 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400340}
341
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500342void FramebufferGL::syncState(const Framebuffer::DirtyBits &dirtyBits)
343{
344 // Don't need to sync state for the default FBO.
345 if (mIsDefault)
346 {
347 return;
348 }
349
350 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
351
352 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
353 {
354 switch (dirtyBit)
355 {
356 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
357 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400358 mState.getDepthAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500359 break;
360 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
361 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400362 mState.getStencilAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500363 break;
364 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
365 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400366 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500367 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
368 drawBuffers.data());
369 break;
370 }
371 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400372 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500373 break;
374 default:
375 {
376 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
377 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
378 size_t index =
379 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
380 BindFramebufferAttachment(mFunctions,
381 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400382 mState.getColorAttachment(index));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500383 break;
384 }
385 }
386 }
387}
388
Geoff Lang4ad17092015-03-10 16:47:44 -0400389GLuint FramebufferGL::getFramebufferID() const
390{
391 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500392}
393
Geoff Langafd7f0a2015-09-09 15:33:31 -0400394void FramebufferGL::syncDrawState() const
395{
396 if (mFunctions->standard == STANDARD_GL_DESKTOP)
397 {
398 // Enable SRGB blending for all framebuffers except the default framebuffer on Desktop
399 // OpenGL.
400 // When SRGB blending is enabled, only SRGB capable formats will use it but the default
401 // framebuffer will always use it if it is enabled.
402 // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
403 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
404 }
405}
406
407void FramebufferGL::syncClearState(GLbitfield mask)
408{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400409 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400410 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400411 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
412 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400413 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400414 bool hasSRBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400415 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400416 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400417 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
418 {
419 hasSRBAttachment = true;
420 break;
421 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400422 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400423
Frank Henigmana3d333c2016-03-22 22:09:14 -0400424 mStateManager->setFramebufferSRGBEnabled(hasSRBAttachment);
425 }
426 else
427 {
428 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
429 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400430 }
431}
432
433void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
434{
435 if (mFunctions->standard == STANDARD_GL_DESKTOP)
436 {
437 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
438 !mIsDefault)
439 {
440 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
441 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400442 const auto &drawbufferState = mState.getDrawBufferStates();
443 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400444
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500445 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400446 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
447 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
448 {
449 size_t attachmentIdx =
450 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
451 attachment = &colorAttachments[attachmentIdx];
452 }
453
454 if (attachment != nullptr)
455 {
456 mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
457 }
458 }
459 else
460 {
461 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
462 }
463 }
464}
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400465gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
466 GLenum format,
467 GLenum type,
468 const gl::PixelPackState &pack,
469 GLvoid *pixels) const
470{
471 intptr_t offset = reinterpret_cast<intptr_t>(pixels);
472
473 const gl::InternalFormat &glFormat =
474 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
475 GLuint rowBytes = 0;
476 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
477 rowBytes);
478 GLuint skipBytes = 0;
479 ANGLE_TRY_RESULT(
480 glFormat.computeSkipBytes(rowBytes, 0, 0, pack.skipRows, pack.skipPixels, false),
481 skipBytes);
482
483 gl::PixelPackState directPack;
484 directPack.pixelBuffer = pack.pixelBuffer;
485 directPack.alignment = 1;
486 mStateManager->setPixelPackState(directPack);
487 directPack.pixelBuffer.set(nullptr);
488
489 offset += skipBytes;
490 for (GLint row = 0; row < area.height; ++row)
491 {
492 mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
493 reinterpret_cast<GLvoid *>(offset));
494 offset += row * rowBytes;
495 }
496
497 return gl::NoError();
498}
499
500gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
501 GLenum format,
502 GLenum type,
503 const gl::PixelPackState &pack,
504 GLvoid *pixels) const
505{
506 const gl::InternalFormat &glFormat =
507 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
508 GLuint rowBytes = 0;
509 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
510 rowBytes);
511 GLuint skipBytes = 0;
512 ANGLE_TRY_RESULT(
513 glFormat.computeSkipBytes(rowBytes, 0, 0, pack.skipRows, pack.skipPixels, false),
514 skipBytes);
515
516 // Get all by the last row
517 if (area.height > 1)
518 {
519 mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
520 }
521
522 // Get the last row manually
523 gl::PixelPackState directPack;
524 directPack.pixelBuffer = pack.pixelBuffer;
525 directPack.alignment = 1;
526 mStateManager->setPixelPackState(directPack);
527 directPack.pixelBuffer.set(nullptr);
528
529 intptr_t lastRowOffset =
530 reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
531 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
532 reinterpret_cast<GLvoid *>(lastRowOffset));
533
534 return gl::NoError();
535}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500536} // namespace rx