blob: 4a9a413d9a997451fbd0da221a32e57be34a9ee1 [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 Madill20e005b2017-04-07 14:19:22 -040011#include "common/bitset_utils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Jamie Madillc564c072017-06-01 12:45:42 -040013#include "libANGLE/Context.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040014#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040015#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040016#include "libANGLE/angletypes.h"
17#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040018#include "libANGLE/renderer/ContextImpl.h"
Corentin Wallez26a717b2016-09-27 08:45:42 -070019#include "libANGLE/renderer/gl/BlitGL.h"
Frank Henigmanfa36c332017-06-09 18:44:45 -040020#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040021#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020022#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040023#include "libANGLE/renderer/gl/StateManagerGL.h"
24#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langafd7f0a2015-09-09 15:33:31 -040025#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Geoff Langf607c602016-09-21 11:46:48 -040026#include "libANGLE/renderer/gl/formatutilsgl.h"
Corentin Wallez886de362016-09-27 10:49:35 -040027#include "libANGLE/renderer/gl/renderergl_utils.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050028#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050029
Jamie Madill60ec6ea2016-01-22 15:27:19 -050030using namespace gl;
Corentin Wallez9a8d3662016-09-22 12:18:29 -040031using angle::CheckedNumeric;
Jamie Madill60ec6ea2016-01-22 15:27:19 -050032
Geoff Langf9a6f082015-01-22 13:32:49 -050033namespace rx
34{
35
Martin Radev878c8b12017-07-28 09:51:04 +030036namespace
Geoff Lang4ad17092015-03-10 16:47:44 -040037{
Geoff Langf9a6f082015-01-22 13:32:49 -050038
Martin Radev878c8b12017-07-28 09:51:04 +030039void BindFramebufferAttachment(const FunctionsGL *functions,
40 GLenum attachmentPoint,
41 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -040042{
43 if (attachment)
44 {
45 if (attachment->type() == GL_TEXTURE)
46 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050047 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040048 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
49
JiangYizhoubddc46b2016-12-09 09:50:51 +080050 if (texture->getTarget() == GL_TEXTURE_2D ||
51 texture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE)
Geoff Lang4ad17092015-03-10 16:47:44 -040052 {
JiangYizhoubddc46b2016-12-09 09:50:51 +080053 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
54 texture->getTarget(), textureGL->getTextureID(),
55 attachment->mipLevel());
Geoff Lang4ad17092015-03-10 16:47:44 -040056 }
57 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
58 {
Jamie Madill231c7f52017-04-26 13:45:37 -040059 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
60 attachment->cubeMapFace(),
Geoff Lang4ad17092015-03-10 16:47:44 -040061 textureGL->getTextureID(), attachment->mipLevel());
62 }
Jamie Madill231c7f52017-04-26 13:45:37 -040063 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY ||
64 texture->getTarget() == GL_TEXTURE_3D)
Geoff Lang4ad17092015-03-10 16:47:44 -040065 {
Jamie Madill231c7f52017-04-26 13:45:37 -040066 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
67 textureGL->getTextureID(),
Geoff Lang4ad17092015-03-10 16:47:44 -040068 attachment->mipLevel(), attachment->layer());
69 }
70 else
71 {
72 UNREACHABLE();
73 }
74 }
75 else if (attachment->type() == GL_RENDERBUFFER)
76 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050077 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040078 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040079
Geoff Langcd69f1c2015-03-18 14:33:23 -040080 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
81 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -040082 }
83 else
84 {
85 UNREACHABLE();
86 }
87 }
88 else
89 {
90 // Unbind this attachment
91 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
92 }
93}
Geoff Langf9a6f082015-01-22 13:32:49 -050094
Martin Radev878c8b12017-07-28 09:51:04 +030095void RetrieveMultiviewFieldsFromAttachment(const gl::FramebufferAttachment *attachment,
96 const std::vector<gl::Offset> **viewportOffsets,
97 GLenum *multiviewLayout)
98{
99 if (attachment)
100 {
101 *viewportOffsets = &attachment->getMultiviewViewportOffsets();
102 *multiviewLayout = attachment->getMultiviewLayout();
103 }
104}
105
Martin Radevb0761932017-07-25 17:42:25 +0300106bool RequiresMultipleClears(const FramebufferAttachment *attachment)
107{
108 return attachment != nullptr &&
109 attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
110}
111
Martin Radev878c8b12017-07-28 09:51:04 +0300112} // namespace
113
114FramebufferGL::FramebufferGL(const FramebufferState &state,
115 const FunctionsGL *functions,
116 StateManagerGL *stateManager,
117 const WorkaroundsGL &workarounds,
118 BlitGL *blitter,
119 bool isDefault)
120 : FramebufferImpl(state),
121 mFunctions(functions),
122 mStateManager(stateManager),
123 mWorkarounds(workarounds),
124 mBlitter(blitter),
125 mFramebufferID(0),
126 mIsDefault(isDefault),
127 mAppliedEnabledDrawBuffers(1)
128{
129 if (!mIsDefault)
130 {
131 mFunctions->genFramebuffers(1, &mFramebufferID);
132 }
133}
134
135FramebufferGL::FramebufferGL(GLuint id,
136 const FramebufferState &state,
137 const FunctionsGL *functions,
138 const WorkaroundsGL &workarounds,
139 BlitGL *blitter,
140 StateManagerGL *stateManager)
141 : FramebufferImpl(state),
142 mFunctions(functions),
143 mStateManager(stateManager),
144 mWorkarounds(workarounds),
145 mBlitter(blitter),
146 mFramebufferID(id),
147 mIsDefault(true),
148 mAppliedEnabledDrawBuffers(1)
149{
150}
151
152FramebufferGL::~FramebufferGL()
153{
154 mStateManager->deleteFramebuffer(mFramebufferID);
155 mFramebufferID = 0;
156}
157
Jamie Madill4928b7c2017-06-20 12:57:39 -0400158Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700159{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500160 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400161 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700162}
163
Jamie Madill4928b7c2017-06-20 12:57:39 -0400164Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500165{
Geoff Lang005a7012017-03-27 13:17:34 -0400166 const GLenum *finalAttachmentsPtr = attachments;
167
168 std::vector<GLenum> modifiedAttachments;
169 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
170 {
171 finalAttachmentsPtr = modifiedAttachments.data();
172 }
173
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500174 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400175 if (mFunctions->invalidateFramebuffer)
176 {
177 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400178 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
179 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400180 }
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500181 else if (mFunctions->discardFramebuffer)
182 {
183 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400184 mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
185 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500186 }
Geoff Lang64a72442015-04-01 14:43:11 -0400187
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500188 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500189}
190
Jamie Madill4928b7c2017-06-20 12:57:39 -0400191Error FramebufferGL::invalidateSub(const gl::Context *context,
192 size_t count,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500193 const GLenum *attachments,
194 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500195{
Geoff Lang005a7012017-03-27 13:17:34 -0400196
197 const GLenum *finalAttachmentsPtr = attachments;
198
199 std::vector<GLenum> modifiedAttachments;
200 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
201 {
202 finalAttachmentsPtr = modifiedAttachments.data();
203 }
204
Jamie Madill231c7f52017-04-26 13:45:37 -0400205 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
206 // available.
Geoff Lang64a72442015-04-01 14:43:11 -0400207 if (mFunctions->invalidateSubFramebuffer)
208 {
209 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700210 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
Geoff Lang005a7012017-03-27 13:17:34 -0400211 finalAttachmentsPtr, area.x, area.y, area.width,
212 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400213 }
214
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500215 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500216}
217
Jamie Madillc564c072017-06-01 12:45:42 -0400218Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500219{
Frank Henigman308d7452017-02-15 22:51:21 -0500220 syncClearState(context, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400221 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300222
223 if (RequiresMultipleClears(mState.getFirstNonNullAttachment()))
224 {
225 genericSideBySideClear(context, ClearCommandType::Clear, mask, GL_NONE, 0, nullptr, 0.0f,
226 0);
227 }
228 else
229 {
230 mFunctions->clear(mask);
231 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400232
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500233 return gl::NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400234}
235
Jamie Madillc564c072017-06-01 12:45:42 -0400236Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500237 GLenum buffer,
238 GLint drawbuffer,
239 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500240{
Frank Henigman308d7452017-02-15 22:51:21 -0500241 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400242 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300243
244 if (RequiresMultipleClears(mState.getFirstNonNullAttachment()))
245 {
246 genericSideBySideClear(context, ClearCommandType::ClearBufferfv,
247 static_cast<GLbitfield>(0u), buffer, drawbuffer,
248 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
249 }
250 else
251 {
252 mFunctions->clearBufferfv(buffer, drawbuffer, values);
253 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400254
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500255 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500256}
257
Jamie Madillc564c072017-06-01 12:45:42 -0400258Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500259 GLenum buffer,
260 GLint drawbuffer,
261 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500262{
Frank Henigman308d7452017-02-15 22:51:21 -0500263 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400264 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300265
266 if (RequiresMultipleClears(mState.getFirstNonNullAttachment()))
267 {
268 genericSideBySideClear(context, ClearCommandType::ClearBufferuiv,
269 static_cast<GLbitfield>(0u), buffer, drawbuffer,
270 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
271 }
272 else
273 {
274 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
275 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400276
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500277 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500278}
279
Jamie Madillc564c072017-06-01 12:45:42 -0400280Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500281 GLenum buffer,
282 GLint drawbuffer,
283 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500284{
Frank Henigman308d7452017-02-15 22:51:21 -0500285 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400286 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300287
288 if (RequiresMultipleClears(mState.getFirstNonNullAttachment()))
289 {
290 genericSideBySideClear(context, ClearCommandType::ClearBufferiv,
291 static_cast<GLbitfield>(0u), buffer, drawbuffer,
292 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
293 }
294 else
295 {
296 mFunctions->clearBufferiv(buffer, drawbuffer, values);
297 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400298
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500299 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500300}
301
Jamie Madillc564c072017-06-01 12:45:42 -0400302Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500303 GLenum buffer,
304 GLint drawbuffer,
305 GLfloat depth,
306 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500307{
Frank Henigman308d7452017-02-15 22:51:21 -0500308 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400309 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300310
311 if (RequiresMultipleClears(mState.getFirstNonNullAttachment()))
312 {
313 genericSideBySideClear(context, ClearCommandType::ClearBufferfi,
314 static_cast<GLbitfield>(0u), buffer, drawbuffer, nullptr, depth,
315 stencil);
316 }
317 else
318 {
319 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
320 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400321
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500322 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500323}
324
Martin Radevb0761932017-07-25 17:42:25 +0300325void FramebufferGL::genericSideBySideClear(const gl::Context *context,
326 ClearCommandType clearCommandType,
327 GLbitfield mask,
328 GLenum buffer,
329 GLint drawbuffer,
330 const uint8_t *values,
331 GLfloat depth,
332 GLint stencil)
333{
334 // For side-by-side framebuffers we have to go over each view and set its scissor rectangle
335 // as the first one and just then call Clear*. This is necessary because Clear* commands use
336 // only the first viewport's scissor rectangle.
337 const auto &scissorBase = context->getGLState().getScissor();
338 const FramebufferAttachment *attachment = mState.getFirstNonNullAttachment();
339 ASSERT(attachment != nullptr);
340 const auto &viewportOffsets = attachment->getMultiviewViewportOffsets();
341
342 for (size_t i = 0u; i < viewportOffsets.size(); ++i)
343 {
344 gl::Rectangle scissor(scissorBase.x + viewportOffsets[i].x,
345 scissorBase.y + viewportOffsets[i].y, scissorBase.width,
346 scissorBase.height);
347 mStateManager->setScissorIndexed(0u, scissor);
348 switch (clearCommandType)
349 {
350 case ClearCommandType::Clear:
351 mFunctions->clear(mask);
352 break;
353 case ClearCommandType::ClearBufferfv:
354 mFunctions->clearBufferfv(buffer, drawbuffer,
355 reinterpret_cast<const GLfloat *>(values));
356 break;
357 case ClearCommandType::ClearBufferuiv:
358 mFunctions->clearBufferuiv(buffer, drawbuffer,
359 reinterpret_cast<const GLuint *>(values));
360 break;
361 case ClearCommandType::ClearBufferiv:
362 mFunctions->clearBufferiv(buffer, drawbuffer,
363 reinterpret_cast<const GLint *>(values));
364 break;
365 case ClearCommandType::ClearBufferfi:
366 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
367 break;
368 default:
369 UNREACHABLE();
370 }
371 }
372}
373
Jamie Madill4928b7c2017-06-20 12:57:39 -0400374GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500375{
Jamie Madilla3944d42016-07-22 22:13:26 -0400376 const auto *readAttachment = mState.getReadAttachment();
377 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400378 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500379}
380
Jamie Madill4928b7c2017-06-20 12:57:39 -0400381GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500382{
Jamie Madilla3944d42016-07-22 22:13:26 -0400383 const auto *readAttachment = mState.getReadAttachment();
384 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400385 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500386}
387
Jamie Madillc564c072017-06-01 12:45:42 -0400388Error FramebufferGL::readPixels(const gl::Context *context,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400389 const gl::Rectangle &origArea,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500390 GLenum format,
391 GLenum type,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400392 void *ptrOrOffset) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500393{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400394 // Clip read area to framebuffer.
395 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
396 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
397 gl::Rectangle area;
398 if (!ClipRectangle(origArea, fbRect, &area))
399 {
400 // nothing to read
401 return gl::NoError();
402 }
403
404 PixelPackState packState;
405 packState.copyFrom(context, context->getGLState().getPackState());
Jamie Madill87de3622015-03-16 10:41:44 -0400406
Geoff Langf607c602016-09-21 11:46:48 -0400407 nativegl::ReadPixelsFormat readPixelsFormat =
408 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400409 GLenum readFormat = readPixelsFormat.format;
410 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400411
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400412 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
413
Frank Henigmanfa36c332017-06-09 18:44:45 -0400414 bool useOverlappingRowsWorkaround = mWorkarounds.packOverlappingRowsSeparatelyPackBuffer &&
415 packState.pixelBuffer.get() && packState.rowLength != 0 &&
416 packState.rowLength < area.width;
417
418 GLubyte *pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
419 int leftClip = area.x - origArea.x;
420 int topClip = area.y - origArea.y;
421 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400422 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400423 // Adjust destination to match portion clipped off left and/or top.
424 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
425
426 GLuint rowBytes = 0;
427 ANGLE_TRY_RESULT(glFormat.computeRowPitch(readType, origArea.width, packState.alignment,
428 packState.rowLength),
429 rowBytes);
430 pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400431 }
432
Frank Henigmanfa36c332017-06-09 18:44:45 -0400433 if (packState.rowLength == 0 && area.width != origArea.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400434 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400435 // No rowLength was specified so it will derive from read width, but clipping changed the
436 // read width. Use the original width so we fill the user's buffer as they intended.
437 packState.rowLength = origArea.width;
438 }
Corentin Wallez886de362016-09-27 10:49:35 -0400439
Frank Henigmanfa36c332017-06-09 18:44:45 -0400440 // We want to use rowLength, but that might not be supported.
441 bool cannotSetDesiredRowLength =
442 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400443
Frank Henigmanfa36c332017-06-09 18:44:45 -0400444 gl::Error retVal = gl::NoError();
445 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
446 {
447 retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
448 }
449 else
450 {
451 gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
452 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400453 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400454 useLastRowPaddingWorkaround =
455 ShouldApplyLastRowPaddingWorkaround(gl::Extents(area.width, area.height, 1),
456 packState, readFormat, readType, false, pixels);
457 }
458
459 if (useLastRowPaddingWorkaround.isError())
460 {
461 retVal = useLastRowPaddingWorkaround.getError();
462 }
463 else
464 {
465 retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
466 useLastRowPaddingWorkaround.getResult());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400467 }
468 }
469
Frank Henigmanfa36c332017-06-09 18:44:45 -0400470 packState.pixelBuffer.set(context, nullptr);
471 return retVal;
Geoff Langf9a6f082015-01-22 13:32:49 -0500472}
473
Jamie Madillc564c072017-06-01 12:45:42 -0400474Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500475 const gl::Rectangle &sourceArea,
476 const gl::Rectangle &destArea,
477 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400478 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500479{
Jamie Madill231c7f52017-04-26 13:45:37 -0400480 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
481 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400482
Corentin Wallez6898b352016-11-10 11:41:15 -0500483 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500484
485 GLsizei readAttachmentSamples = 0;
486 if (colorReadAttachment != nullptr)
487 {
488 readAttachmentSamples = colorReadAttachment->getSamples();
489 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500490
Corentin Wallez26a717b2016-09-27 08:45:42 -0700491 bool needManualColorBlit = false;
492
Corentin Wallez6898b352016-11-10 11:41:15 -0500493 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
494 // could avoid doing a manual blit.
495
496 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
497 // When values are taken from the read buffer, no linearization is performed, even
498 // if the format of the buffer is SRGB.
499 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
500 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
501 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
502 // corresponding to the read buffer is SRGB, the red, green, and blue components are
503 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700504 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400505 bool sourceSRGB =
506 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500507 needManualColorBlit =
508 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
509 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700510
Corentin Wallez6898b352016-11-10 11:41:15 -0500511 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
512 // Blit operations bypass the fragment pipeline. The only fragment operations which
513 // affect a blit are the pixel ownership test and scissor test.
514 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
515 // When values are written to the draw buffers, blit operations bypass the fragment
516 // pipeline. The only fragment operations which affect a blit are the pixel ownership
517 // test, the scissor test and sRGB conversion.
518 if (!needManualColorBlit)
519 {
520 bool destSRGB = false;
521 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700522 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500523 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
524 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700525 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500526 destSRGB = true;
527 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700528 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700529 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500530
531 needManualColorBlit =
532 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700533 }
534
535 // Enable FRAMEBUFFER_SRGB if needed
Jamie Madill4928b7c2017-06-20 12:57:39 -0400536 mStateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700537
538 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500539 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700540 {
541 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
542 sourceArea, destArea, filter));
543 blitMask &= ~GL_COLOR_BUFFER_BIT;
544 }
545
546 if (blitMask == 0)
547 {
548 return gl::NoError();
549 }
550
551 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400552 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
553 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
554
Jamie Madill2da819e2015-12-03 15:53:19 -0500555 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700556 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
557 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400558
Corentin Wallez26a717b2016-09-27 08:45:42 -0700559 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500560}
561
JiangYizhoubddc46b2016-12-09 09:50:51 +0800562gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
563{
564 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
565 mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
566 return gl::NoError();
567}
568
Jamie Madillcc86d642015-11-24 13:00:07 -0500569bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500570{
Geoff Lang4ad17092015-03-10 16:47:44 -0400571 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500572 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
573 if (status != GL_FRAMEBUFFER_COMPLETE)
574 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500575 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500576 }
577 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400578}
579
Jamie Madillc564c072017-06-01 12:45:42 -0400580void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500581{
582 // Don't need to sync state for the default FBO.
583 if (mIsDefault)
584 {
585 return;
586 }
587
588 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
589
Martin Radev878c8b12017-07-28 09:51:04 +0300590 const std::vector<gl::Offset> *attachmentViewportOffsets = nullptr;
591 GLenum multiviewLayout = GL_NONE;
592 bool isAttachmentModified = false;
593
Jamie Madill6de51852017-04-12 09:53:01 -0400594 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500595 {
596 switch (dirtyBit)
597 {
598 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
599 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400600 mState.getDepthAttachment());
Martin Radev878c8b12017-07-28 09:51:04 +0300601 RetrieveMultiviewFieldsFromAttachment(mState.getDepthAttachment(),
602 &attachmentViewportOffsets, &multiviewLayout);
603 isAttachmentModified = true;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500604 break;
605 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
606 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400607 mState.getStencilAttachment());
Martin Radev878c8b12017-07-28 09:51:04 +0300608 RetrieveMultiviewFieldsFromAttachment(mState.getStencilAttachment(),
609 &attachmentViewportOffsets, &multiviewLayout);
610 isAttachmentModified = true;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500611 break;
612 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
613 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400614 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500615 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
616 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400617 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500618 break;
619 }
620 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400621 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500622 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800623 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
624 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
625 mState.getDefaultWidth());
626 break;
627 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
628 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
629 mState.getDefaultHeight());
630 break;
631 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
632 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
633 mState.getDefaultSamples());
634 break;
635 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
636 mFunctions->framebufferParameteri(GL_FRAMEBUFFER,
637 GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
638 mState.getDefaultFixedSampleLocations());
639 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500640 default:
641 {
642 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
643 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
644 size_t index =
645 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
646 BindFramebufferAttachment(mFunctions,
647 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400648 mState.getColorAttachment(index));
Martin Radev878c8b12017-07-28 09:51:04 +0300649 RetrieveMultiviewFieldsFromAttachment(mState.getColorAttachment(index),
650 &attachmentViewportOffsets, &multiviewLayout);
651 isAttachmentModified = true;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500652 break;
653 }
654 }
655 }
Martin Radev878c8b12017-07-28 09:51:04 +0300656
657 if (isAttachmentModified)
658 {
659 const bool isSideBySide = multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
660 mStateManager->setSideBySide(isSideBySide);
661 mStateManager->setScissorTestEnabled(isSideBySide ||
662 context->getGLState().isScissorTestEnabled());
663 if (attachmentViewportOffsets != nullptr)
664 {
665 mStateManager->setViewportOffsets(*attachmentViewportOffsets);
666 }
667 else
668 {
669 mStateManager->setViewportOffsets(
670 FramebufferAttachment::GetDefaultViewportOffsetVector());
671 }
672 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500673}
674
Geoff Lang4ad17092015-03-10 16:47:44 -0400675GLuint FramebufferGL::getFramebufferID() const
676{
677 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500678}
679
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700680bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400681{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700682 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400683}
684
Corentin Walleze7557742017-06-01 13:09:57 -0400685void FramebufferGL::maskOutInactiveOutputDrawBuffers(DrawBufferMask maxSet)
686{
687 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
688 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
689 {
690 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
691
692 const auto &stateDrawBuffers = mState.getDrawBufferStates();
693 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
694 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
695
696 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
697 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
698 {
699 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
700 }
701
702 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
703 mFunctions->drawBuffers(drawBufferCount, drawBuffers);
704 }
705}
706
Jamie Madillc564c072017-06-01 12:45:42 -0400707void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400708{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400709 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400710 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400711 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
712 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400713 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700714 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400715 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400716 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400717 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
718 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700719 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400720 break;
721 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400722 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400723
Jamie Madill4928b7c2017-06-20 12:57:39 -0400724 mStateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400725 }
726 else
727 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400728 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400729 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400730 }
731}
732
Jamie Madillc564c072017-06-01 12:45:42 -0400733void FramebufferGL::syncClearBufferState(const gl::Context *context,
734 GLenum buffer,
735 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400736{
737 if (mFunctions->standard == STANDARD_GL_DESKTOP)
738 {
739 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
740 !mIsDefault)
741 {
742 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
743 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400744 const auto &drawbufferState = mState.getDrawBufferStates();
745 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400746
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500747 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400748 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
749 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
750 {
751 size_t attachmentIdx =
752 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
753 attachment = &colorAttachments[attachmentIdx];
754 }
755
756 if (attachment != nullptr)
757 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400758 mStateManager->setFramebufferSRGBEnabled(context,
Frank Henigman308d7452017-02-15 22:51:21 -0500759 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400760 }
761 }
762 else
763 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400764 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400765 }
766 }
767}
Geoff Lang005a7012017-03-27 13:17:34 -0400768
769bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
770 size_t count,
771 const GLenum *attachments,
772 std::vector<GLenum> *modifiedAttachments) const
773{
774 bool needsModification = mIsDefault && mFramebufferID != 0;
775 if (!needsModification)
776 {
777 return false;
778 }
779
780 modifiedAttachments->resize(count);
781 for (size_t i = 0; i < count; i++)
782 {
783 switch (attachments[i])
784 {
785 case GL_COLOR:
786 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
787 break;
788
789 case GL_DEPTH:
790 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
791 break;
792
793 case GL_STENCIL:
794 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
795 break;
796
797 default:
798 UNREACHABLE();
799 break;
800 }
801 }
802
803 return true;
804}
805
Frank Henigmanfa36c332017-06-09 18:44:45 -0400806gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
807 const gl::Rectangle &area,
808 GLenum format,
809 GLenum type,
810 const gl::PixelPackState &pack,
811 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400812{
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400813
Geoff Langca271392017-04-05 12:30:00 -0400814 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400815
816 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400817 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
818 rowBytes);
819 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400820 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400821
822 gl::PixelPackState directPack;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400823 directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400824 directPack.alignment = 1;
825 mStateManager->setPixelPackState(directPack);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400826 directPack.pixelBuffer.set(context, nullptr);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400827
Frank Henigmanfa36c332017-06-09 18:44:45 -0400828 pixels += skipBytes;
829 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400830 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400831 mFunctions->readPixels(area.x, y, area.width, 1, format, type, pixels);
832 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400833 }
834
835 return gl::NoError();
836}
837
Frank Henigmanfa36c332017-06-09 18:44:45 -0400838gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
839 const gl::Rectangle &area,
840 GLenum format,
841 GLenum type,
842 const gl::PixelPackState &pack,
843 GLubyte *pixels,
844 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400845{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400846 GLint height = area.height - readLastRowSeparately;
847 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400848 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400849 mStateManager->setPixelPackState(pack);
850 mFunctions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400851 }
852
Frank Henigmanfa36c332017-06-09 18:44:45 -0400853 if (readLastRowSeparately)
854 {
855 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400856
Frank Henigmanfa36c332017-06-09 18:44:45 -0400857 GLuint rowBytes = 0;
858 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
859 rowBytes);
860 GLuint skipBytes = 0;
861 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
862
863 gl::PixelPackState directPack;
864 directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
865 directPack.alignment = 1;
866 mStateManager->setPixelPackState(directPack);
867 directPack.pixelBuffer.set(context, nullptr);
868
869 pixels += skipBytes + (area.height - 1) * rowBytes;
870 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
871 pixels);
872 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400873
874 return gl::NoError();
875}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500876} // namespace rx