1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // BlitGL.cpp: Implements the BlitGL class, a helper for blitting textures
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/BlitGL.h"
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include "common/FixedVector.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/vector_utils.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "image_util/copyimage.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Framebuffer.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/Format.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/ContextGL.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/FramebufferGL.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/FunctionsGL.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/RenderbufferGL.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/StateManagerGL.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/TextureGL.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/formatutilsgl.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/renderergl_utils.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/renderer_utils.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "platform/autogen/FeaturesGL_autogen.h"
29*8975f5c5SAndroid Build Coastguard Worker
30*8975f5c5SAndroid Build Coastguard Worker using angle::Vector2;
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Worker namespace rx
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker
35*8975f5c5SAndroid Build Coastguard Worker namespace
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker
CheckCompileStatus(const gl::Context * context,const rx::FunctionsGL * functions,GLuint shader)38*8975f5c5SAndroid Build Coastguard Worker angle::Result CheckCompileStatus(const gl::Context *context,
39*8975f5c5SAndroid Build Coastguard Worker const rx::FunctionsGL *functions,
40*8975f5c5SAndroid Build Coastguard Worker GLuint shader)
41*8975f5c5SAndroid Build Coastguard Worker {
42*8975f5c5SAndroid Build Coastguard Worker GLint compileStatus = GL_FALSE;
43*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, functions->getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus));
44*8975f5c5SAndroid Build Coastguard Worker
45*8975f5c5SAndroid Build Coastguard Worker ASSERT(compileStatus == GL_TRUE);
46*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK(GetImplAs<ContextGL>(context), compileStatus == GL_TRUE,
47*8975f5c5SAndroid Build Coastguard Worker "Failed to compile internal blit shader.", GL_OUT_OF_MEMORY);
48*8975f5c5SAndroid Build Coastguard Worker
49*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
50*8975f5c5SAndroid Build Coastguard Worker }
51*8975f5c5SAndroid Build Coastguard Worker
CheckLinkStatus(const gl::Context * context,const rx::FunctionsGL * functions,GLuint program)52*8975f5c5SAndroid Build Coastguard Worker angle::Result CheckLinkStatus(const gl::Context *context,
53*8975f5c5SAndroid Build Coastguard Worker const rx::FunctionsGL *functions,
54*8975f5c5SAndroid Build Coastguard Worker GLuint program)
55*8975f5c5SAndroid Build Coastguard Worker {
56*8975f5c5SAndroid Build Coastguard Worker GLint linkStatus = GL_FALSE;
57*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, functions->getProgramiv(program, GL_LINK_STATUS, &linkStatus));
58*8975f5c5SAndroid Build Coastguard Worker ASSERT(linkStatus == GL_TRUE);
59*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK(GetImplAs<ContextGL>(context), linkStatus == GL_TRUE,
60*8975f5c5SAndroid Build Coastguard Worker "Failed to link internal blit program.", GL_OUT_OF_MEMORY);
61*8975f5c5SAndroid Build Coastguard Worker
62*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
63*8975f5c5SAndroid Build Coastguard Worker }
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker class [[nodiscard]] ScopedGLState : angle::NonCopyable
66*8975f5c5SAndroid Build Coastguard Worker {
67*8975f5c5SAndroid Build Coastguard Worker public:
68*8975f5c5SAndroid Build Coastguard Worker enum
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker KEEP_SCISSOR = 1,
71*8975f5c5SAndroid Build Coastguard Worker };
72*8975f5c5SAndroid Build Coastguard Worker
ScopedGLState()73*8975f5c5SAndroid Build Coastguard Worker ScopedGLState() {}
74*8975f5c5SAndroid Build Coastguard Worker
~ScopedGLState()75*8975f5c5SAndroid Build Coastguard Worker ~ScopedGLState() { ASSERT(mExited); }
76*8975f5c5SAndroid Build Coastguard Worker
enter(const gl::Context * context,gl::Rectangle viewport,int keepState=0)77*8975f5c5SAndroid Build Coastguard Worker angle::Result enter(const gl::Context *context, gl::Rectangle viewport, int keepState = 0)
78*8975f5c5SAndroid Build Coastguard Worker {
79*8975f5c5SAndroid Build Coastguard Worker ContextGL *contextGL = GetImplAs<ContextGL>(context);
80*8975f5c5SAndroid Build Coastguard Worker StateManagerGL *stateManager = contextGL->getStateManager();
81*8975f5c5SAndroid Build Coastguard Worker
82*8975f5c5SAndroid Build Coastguard Worker if (!(keepState & KEEP_SCISSOR))
83*8975f5c5SAndroid Build Coastguard Worker {
84*8975f5c5SAndroid Build Coastguard Worker stateManager->setScissorTestEnabled(false);
85*8975f5c5SAndroid Build Coastguard Worker }
86*8975f5c5SAndroid Build Coastguard Worker stateManager->setViewport(viewport);
87*8975f5c5SAndroid Build Coastguard Worker stateManager->setDepthRange(0.0f, 1.0f);
88*8975f5c5SAndroid Build Coastguard Worker stateManager->setClipControl(gl::ClipOrigin::LowerLeft,
89*8975f5c5SAndroid Build Coastguard Worker gl::ClipDepthMode::NegativeOneToOne);
90*8975f5c5SAndroid Build Coastguard Worker stateManager->setClipDistancesEnable(gl::ClipDistanceEnableBits());
91*8975f5c5SAndroid Build Coastguard Worker stateManager->setDepthClampEnabled(false);
92*8975f5c5SAndroid Build Coastguard Worker stateManager->setBlendEnabled(false);
93*8975f5c5SAndroid Build Coastguard Worker stateManager->setColorMask(true, true, true, true);
94*8975f5c5SAndroid Build Coastguard Worker stateManager->setSampleAlphaToCoverageEnabled(false);
95*8975f5c5SAndroid Build Coastguard Worker stateManager->setSampleCoverageEnabled(false);
96*8975f5c5SAndroid Build Coastguard Worker stateManager->setDepthTestEnabled(false);
97*8975f5c5SAndroid Build Coastguard Worker stateManager->setStencilTestEnabled(false);
98*8975f5c5SAndroid Build Coastguard Worker stateManager->setCullFaceEnabled(false);
99*8975f5c5SAndroid Build Coastguard Worker stateManager->setPolygonMode(gl::PolygonMode::Fill);
100*8975f5c5SAndroid Build Coastguard Worker stateManager->setPolygonOffsetPointEnabled(false);
101*8975f5c5SAndroid Build Coastguard Worker stateManager->setPolygonOffsetLineEnabled(false);
102*8975f5c5SAndroid Build Coastguard Worker stateManager->setPolygonOffsetFillEnabled(false);
103*8975f5c5SAndroid Build Coastguard Worker stateManager->setRasterizerDiscardEnabled(false);
104*8975f5c5SAndroid Build Coastguard Worker stateManager->setLogicOpEnabled(false);
105*8975f5c5SAndroid Build Coastguard Worker
106*8975f5c5SAndroid Build Coastguard Worker stateManager->pauseTransformFeedback();
107*8975f5c5SAndroid Build Coastguard Worker return stateManager->pauseAllQueries(context);
108*8975f5c5SAndroid Build Coastguard Worker }
109*8975f5c5SAndroid Build Coastguard Worker
exit(const gl::Context * context)110*8975f5c5SAndroid Build Coastguard Worker angle::Result exit(const gl::Context *context)
111*8975f5c5SAndroid Build Coastguard Worker {
112*8975f5c5SAndroid Build Coastguard Worker mExited = true;
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker ContextGL *contextGL = GetImplAs<ContextGL>(context);
115*8975f5c5SAndroid Build Coastguard Worker StateManagerGL *stateManager = contextGL->getStateManager();
116*8975f5c5SAndroid Build Coastguard Worker
117*8975f5c5SAndroid Build Coastguard Worker // XFB resuming will be done automatically
118*8975f5c5SAndroid Build Coastguard Worker return stateManager->resumeAllQueries(context);
119*8975f5c5SAndroid Build Coastguard Worker }
120*8975f5c5SAndroid Build Coastguard Worker
willUseTextureUnit(const gl::Context * context,int unit)121*8975f5c5SAndroid Build Coastguard Worker void willUseTextureUnit(const gl::Context *context, int unit)
122*8975f5c5SAndroid Build Coastguard Worker {
123*8975f5c5SAndroid Build Coastguard Worker ContextGL *contextGL = GetImplAs<ContextGL>(context);
124*8975f5c5SAndroid Build Coastguard Worker
125*8975f5c5SAndroid Build Coastguard Worker if (contextGL->getFunctions()->bindSampler)
126*8975f5c5SAndroid Build Coastguard Worker {
127*8975f5c5SAndroid Build Coastguard Worker contextGL->getStateManager()->bindSampler(unit, 0);
128*8975f5c5SAndroid Build Coastguard Worker }
129*8975f5c5SAndroid Build Coastguard Worker }
130*8975f5c5SAndroid Build Coastguard Worker
131*8975f5c5SAndroid Build Coastguard Worker private:
132*8975f5c5SAndroid Build Coastguard Worker bool mExited = false;
133*8975f5c5SAndroid Build Coastguard Worker };
134*8975f5c5SAndroid Build Coastguard Worker
SetClearState(StateManagerGL * stateManager,bool colorClear,bool depthClear,bool stencilClear,GLbitfield * outClearMask)135*8975f5c5SAndroid Build Coastguard Worker angle::Result SetClearState(StateManagerGL *stateManager,
136*8975f5c5SAndroid Build Coastguard Worker bool colorClear,
137*8975f5c5SAndroid Build Coastguard Worker bool depthClear,
138*8975f5c5SAndroid Build Coastguard Worker bool stencilClear,
139*8975f5c5SAndroid Build Coastguard Worker GLbitfield *outClearMask)
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker *outClearMask = 0;
142*8975f5c5SAndroid Build Coastguard Worker if (colorClear)
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker stateManager->setClearColor(gl::ColorF(0.0f, 0.0f, 0.0f, 0.0f));
145*8975f5c5SAndroid Build Coastguard Worker stateManager->setColorMask(true, true, true, true);
146*8975f5c5SAndroid Build Coastguard Worker *outClearMask |= GL_COLOR_BUFFER_BIT;
147*8975f5c5SAndroid Build Coastguard Worker }
148*8975f5c5SAndroid Build Coastguard Worker if (depthClear)
149*8975f5c5SAndroid Build Coastguard Worker {
150*8975f5c5SAndroid Build Coastguard Worker stateManager->setDepthMask(true);
151*8975f5c5SAndroid Build Coastguard Worker stateManager->setClearDepth(1.0f);
152*8975f5c5SAndroid Build Coastguard Worker *outClearMask |= GL_DEPTH_BUFFER_BIT;
153*8975f5c5SAndroid Build Coastguard Worker }
154*8975f5c5SAndroid Build Coastguard Worker if (stencilClear)
155*8975f5c5SAndroid Build Coastguard Worker {
156*8975f5c5SAndroid Build Coastguard Worker stateManager->setClearStencil(0);
157*8975f5c5SAndroid Build Coastguard Worker *outClearMask |= GL_STENCIL_BUFFER_BIT;
158*8975f5c5SAndroid Build Coastguard Worker }
159*8975f5c5SAndroid Build Coastguard Worker
160*8975f5c5SAndroid Build Coastguard Worker stateManager->setScissorTestEnabled(false);
161*8975f5c5SAndroid Build Coastguard Worker
162*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
163*8975f5c5SAndroid Build Coastguard Worker }
164*8975f5c5SAndroid Build Coastguard Worker
165*8975f5c5SAndroid Build Coastguard Worker using ClearBindTargetVector = angle::FixedVector<GLenum, 3>;
166*8975f5c5SAndroid Build Coastguard Worker
PrepareForClear(StateManagerGL * stateManager,GLenum sizedInternalFormat,ClearBindTargetVector * outBindtargets,ClearBindTargetVector * outUnbindTargets,GLbitfield * outClearMask)167*8975f5c5SAndroid Build Coastguard Worker angle::Result PrepareForClear(StateManagerGL *stateManager,
168*8975f5c5SAndroid Build Coastguard Worker GLenum sizedInternalFormat,
169*8975f5c5SAndroid Build Coastguard Worker ClearBindTargetVector *outBindtargets,
170*8975f5c5SAndroid Build Coastguard Worker ClearBindTargetVector *outUnbindTargets,
171*8975f5c5SAndroid Build Coastguard Worker GLbitfield *outClearMask)
172*8975f5c5SAndroid Build Coastguard Worker {
173*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &internalFormatInfo =
174*8975f5c5SAndroid Build Coastguard Worker gl::GetSizedInternalFormatInfo(sizedInternalFormat);
175*8975f5c5SAndroid Build Coastguard Worker bool bindDepth = internalFormatInfo.depthBits > 0;
176*8975f5c5SAndroid Build Coastguard Worker bool bindStencil = internalFormatInfo.stencilBits > 0;
177*8975f5c5SAndroid Build Coastguard Worker bool bindColor = !bindDepth && !bindStencil;
178*8975f5c5SAndroid Build Coastguard Worker
179*8975f5c5SAndroid Build Coastguard Worker outBindtargets->clear();
180*8975f5c5SAndroid Build Coastguard Worker if (bindColor)
181*8975f5c5SAndroid Build Coastguard Worker {
182*8975f5c5SAndroid Build Coastguard Worker outBindtargets->push_back(GL_COLOR_ATTACHMENT0);
183*8975f5c5SAndroid Build Coastguard Worker }
184*8975f5c5SAndroid Build Coastguard Worker else
185*8975f5c5SAndroid Build Coastguard Worker {
186*8975f5c5SAndroid Build Coastguard Worker outUnbindTargets->push_back(GL_COLOR_ATTACHMENT0);
187*8975f5c5SAndroid Build Coastguard Worker }
188*8975f5c5SAndroid Build Coastguard Worker if (bindDepth)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker outBindtargets->push_back(GL_DEPTH_ATTACHMENT);
191*8975f5c5SAndroid Build Coastguard Worker }
192*8975f5c5SAndroid Build Coastguard Worker else
193*8975f5c5SAndroid Build Coastguard Worker {
194*8975f5c5SAndroid Build Coastguard Worker outUnbindTargets->push_back(GL_DEPTH_ATTACHMENT);
195*8975f5c5SAndroid Build Coastguard Worker }
196*8975f5c5SAndroid Build Coastguard Worker if (bindStencil)
197*8975f5c5SAndroid Build Coastguard Worker {
198*8975f5c5SAndroid Build Coastguard Worker outBindtargets->push_back(GL_STENCIL_ATTACHMENT);
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker else
201*8975f5c5SAndroid Build Coastguard Worker {
202*8975f5c5SAndroid Build Coastguard Worker outUnbindTargets->push_back(GL_STENCIL_ATTACHMENT);
203*8975f5c5SAndroid Build Coastguard Worker }
204*8975f5c5SAndroid Build Coastguard Worker
205*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(SetClearState(stateManager, bindColor, bindDepth, bindStencil, outClearMask));
206*8975f5c5SAndroid Build Coastguard Worker
207*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker
UnbindAttachment(const gl::Context * context,const FunctionsGL * functions,GLenum framebufferTarget,GLenum attachment)210*8975f5c5SAndroid Build Coastguard Worker angle::Result UnbindAttachment(const gl::Context *context,
211*8975f5c5SAndroid Build Coastguard Worker const FunctionsGL *functions,
212*8975f5c5SAndroid Build Coastguard Worker GLenum framebufferTarget,
213*8975f5c5SAndroid Build Coastguard Worker GLenum attachment)
214*8975f5c5SAndroid Build Coastguard Worker {
215*8975f5c5SAndroid Build Coastguard Worker // Always use framebufferTexture2D as a workaround for an Nvidia driver bug. See
216*8975f5c5SAndroid Build Coastguard Worker // https://anglebug.com/42264072 and FeaturesGL.alwaysUnbindFramebufferTexture2D
217*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
218*8975f5c5SAndroid Build Coastguard Worker functions->framebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0));
219*8975f5c5SAndroid Build Coastguard Worker
220*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
221*8975f5c5SAndroid Build Coastguard Worker }
222*8975f5c5SAndroid Build Coastguard Worker
UnbindAttachments(const gl::Context * context,const FunctionsGL * functions,GLenum framebufferTarget,const ClearBindTargetVector & bindTargets)223*8975f5c5SAndroid Build Coastguard Worker angle::Result UnbindAttachments(const gl::Context *context,
224*8975f5c5SAndroid Build Coastguard Worker const FunctionsGL *functions,
225*8975f5c5SAndroid Build Coastguard Worker GLenum framebufferTarget,
226*8975f5c5SAndroid Build Coastguard Worker const ClearBindTargetVector &bindTargets)
227*8975f5c5SAndroid Build Coastguard Worker {
228*8975f5c5SAndroid Build Coastguard Worker for (GLenum bindTarget : bindTargets)
229*8975f5c5SAndroid Build Coastguard Worker {
230*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, functions, framebufferTarget, bindTarget));
231*8975f5c5SAndroid Build Coastguard Worker }
232*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
233*8975f5c5SAndroid Build Coastguard Worker }
234*8975f5c5SAndroid Build Coastguard Worker
CheckIfAttachmentNeedsClearing(const gl::Context * context,const gl::FramebufferAttachment * attachment,bool * needsClearInit)235*8975f5c5SAndroid Build Coastguard Worker angle::Result CheckIfAttachmentNeedsClearing(const gl::Context *context,
236*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *attachment,
237*8975f5c5SAndroid Build Coastguard Worker bool *needsClearInit)
238*8975f5c5SAndroid Build Coastguard Worker {
239*8975f5c5SAndroid Build Coastguard Worker if (attachment->initState() == gl::InitState::Initialized)
240*8975f5c5SAndroid Build Coastguard Worker {
241*8975f5c5SAndroid Build Coastguard Worker *needsClearInit = false;
242*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
243*8975f5c5SAndroid Build Coastguard Worker }
244*8975f5c5SAndroid Build Coastguard Worker
245*8975f5c5SAndroid Build Coastguard Worker // Special case for 2D array and 3D textures. The init state tracks initialization for all
246*8975f5c5SAndroid Build Coastguard Worker // layers but only one will be cleared by a clear call. Initialize those entire textures
247*8975f5c5SAndroid Build Coastguard Worker // here.
248*8975f5c5SAndroid Build Coastguard Worker if (attachment->type() == GL_TEXTURE &&
249*8975f5c5SAndroid Build Coastguard Worker (attachment->getTextureImageIndex().getTarget() == gl::TextureTarget::_2DArray ||
250*8975f5c5SAndroid Build Coastguard Worker attachment->getTextureImageIndex().getTarget() == gl::TextureTarget::_3D))
251*8975f5c5SAndroid Build Coastguard Worker {
252*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(attachment->initializeContents(context));
253*8975f5c5SAndroid Build Coastguard Worker *needsClearInit = false;
254*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
255*8975f5c5SAndroid Build Coastguard Worker }
256*8975f5c5SAndroid Build Coastguard Worker
257*8975f5c5SAndroid Build Coastguard Worker *needsClearInit = true;
258*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
259*8975f5c5SAndroid Build Coastguard Worker }
260*8975f5c5SAndroid Build Coastguard Worker
261*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
262*8975f5c5SAndroid Build Coastguard Worker
BlitGL(const FunctionsGL * functions,const angle::FeaturesGL & features,StateManagerGL * stateManager)263*8975f5c5SAndroid Build Coastguard Worker BlitGL::BlitGL(const FunctionsGL *functions,
264*8975f5c5SAndroid Build Coastguard Worker const angle::FeaturesGL &features,
265*8975f5c5SAndroid Build Coastguard Worker StateManagerGL *stateManager)
266*8975f5c5SAndroid Build Coastguard Worker : mFunctions(functions),
267*8975f5c5SAndroid Build Coastguard Worker mFeatures(features),
268*8975f5c5SAndroid Build Coastguard Worker mStateManager(stateManager),
269*8975f5c5SAndroid Build Coastguard Worker mScratchFBO(0),
270*8975f5c5SAndroid Build Coastguard Worker mVAO(0),
271*8975f5c5SAndroid Build Coastguard Worker mVertexBuffer(0)
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
274*8975f5c5SAndroid Build Coastguard Worker {
275*8975f5c5SAndroid Build Coastguard Worker mScratchTextures[i] = 0;
276*8975f5c5SAndroid Build Coastguard Worker }
277*8975f5c5SAndroid Build Coastguard Worker
278*8975f5c5SAndroid Build Coastguard Worker ASSERT(mFunctions);
279*8975f5c5SAndroid Build Coastguard Worker ASSERT(mStateManager);
280*8975f5c5SAndroid Build Coastguard Worker }
281*8975f5c5SAndroid Build Coastguard Worker
~BlitGL()282*8975f5c5SAndroid Build Coastguard Worker BlitGL::~BlitGL()
283*8975f5c5SAndroid Build Coastguard Worker {
284*8975f5c5SAndroid Build Coastguard Worker for (const auto &blitProgram : mBlitPrograms)
285*8975f5c5SAndroid Build Coastguard Worker {
286*8975f5c5SAndroid Build Coastguard Worker mStateManager->deleteProgram(blitProgram.second.program);
287*8975f5c5SAndroid Build Coastguard Worker }
288*8975f5c5SAndroid Build Coastguard Worker mBlitPrograms.clear();
289*8975f5c5SAndroid Build Coastguard Worker
290*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
291*8975f5c5SAndroid Build Coastguard Worker {
292*8975f5c5SAndroid Build Coastguard Worker if (mScratchTextures[i] != 0)
293*8975f5c5SAndroid Build Coastguard Worker {
294*8975f5c5SAndroid Build Coastguard Worker mStateManager->deleteTexture(mScratchTextures[i]);
295*8975f5c5SAndroid Build Coastguard Worker mScratchTextures[i] = 0;
296*8975f5c5SAndroid Build Coastguard Worker }
297*8975f5c5SAndroid Build Coastguard Worker }
298*8975f5c5SAndroid Build Coastguard Worker
299*8975f5c5SAndroid Build Coastguard Worker if (mScratchFBO != 0)
300*8975f5c5SAndroid Build Coastguard Worker {
301*8975f5c5SAndroid Build Coastguard Worker mStateManager->deleteFramebuffer(mScratchFBO);
302*8975f5c5SAndroid Build Coastguard Worker mScratchFBO = 0;
303*8975f5c5SAndroid Build Coastguard Worker }
304*8975f5c5SAndroid Build Coastguard Worker
305*8975f5c5SAndroid Build Coastguard Worker if (mOwnsVAOState)
306*8975f5c5SAndroid Build Coastguard Worker {
307*8975f5c5SAndroid Build Coastguard Worker mStateManager->deleteVertexArray(mVAO);
308*8975f5c5SAndroid Build Coastguard Worker SafeDelete(mVAOState);
309*8975f5c5SAndroid Build Coastguard Worker mVAO = 0;
310*8975f5c5SAndroid Build Coastguard Worker }
311*8975f5c5SAndroid Build Coastguard Worker }
312*8975f5c5SAndroid Build Coastguard Worker
copyImageToLUMAWorkaroundTexture(const gl::Context * context,GLuint texture,gl::TextureType textureType,gl::TextureTarget target,GLenum lumaFormat,size_t level,const gl::Rectangle & sourceArea,GLenum internalFormat,gl::Framebuffer * source)313*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::copyImageToLUMAWorkaroundTexture(const gl::Context *context,
314*8975f5c5SAndroid Build Coastguard Worker GLuint texture,
315*8975f5c5SAndroid Build Coastguard Worker gl::TextureType textureType,
316*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget target,
317*8975f5c5SAndroid Build Coastguard Worker GLenum lumaFormat,
318*8975f5c5SAndroid Build Coastguard Worker size_t level,
319*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
320*8975f5c5SAndroid Build Coastguard Worker GLenum internalFormat,
321*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *source)
322*8975f5c5SAndroid Build Coastguard Worker {
323*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(textureType, texture);
324*8975f5c5SAndroid Build Coastguard Worker
325*8975f5c5SAndroid Build Coastguard Worker // Allocate the texture memory
326*8975f5c5SAndroid Build Coastguard Worker GLenum format = gl::GetUnsizedFormat(internalFormat);
327*8975f5c5SAndroid Build Coastguard Worker GLenum readType = source->getImplementationColorReadType(context);
328*8975f5c5SAndroid Build Coastguard Worker
329*8975f5c5SAndroid Build Coastguard Worker // getImplementationColorReadType aligns the type with ES client version
330*8975f5c5SAndroid Build Coastguard Worker if (readType == GL_HALF_FLOAT_OES && mFunctions->standard == STANDARD_GL_DESKTOP)
331*8975f5c5SAndroid Build Coastguard Worker {
332*8975f5c5SAndroid Build Coastguard Worker readType = GL_HALF_FLOAT;
333*8975f5c5SAndroid Build Coastguard Worker }
334*8975f5c5SAndroid Build Coastguard Worker
335*8975f5c5SAndroid Build Coastguard Worker gl::PixelUnpackState unpack;
336*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelUnpackState(context, unpack));
337*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelUnpackBuffer(
338*8975f5c5SAndroid Build Coastguard Worker context, context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack)));
339*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY_ALWAYS_CHECK(
340*8975f5c5SAndroid Build Coastguard Worker context,
341*8975f5c5SAndroid Build Coastguard Worker mFunctions->texImage2D(ToGLenum(target), static_cast<GLint>(level), internalFormat,
342*8975f5c5SAndroid Build Coastguard Worker sourceArea.width, sourceArea.height, 0, format, readType, nullptr));
343*8975f5c5SAndroid Build Coastguard Worker
344*8975f5c5SAndroid Build Coastguard Worker return copySubImageToLUMAWorkaroundTexture(context, texture, textureType, target, lumaFormat,
345*8975f5c5SAndroid Build Coastguard Worker level, gl::Offset(0, 0, 0), sourceArea, source);
346*8975f5c5SAndroid Build Coastguard Worker }
347*8975f5c5SAndroid Build Coastguard Worker
copySubImageToLUMAWorkaroundTexture(const gl::Context * context,GLuint texture,gl::TextureType textureType,gl::TextureTarget target,GLenum lumaFormat,size_t level,const gl::Offset & destOffset,const gl::Rectangle & sourceArea,gl::Framebuffer * source)348*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::copySubImageToLUMAWorkaroundTexture(const gl::Context *context,
349*8975f5c5SAndroid Build Coastguard Worker GLuint texture,
350*8975f5c5SAndroid Build Coastguard Worker gl::TextureType textureType,
351*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget target,
352*8975f5c5SAndroid Build Coastguard Worker GLenum lumaFormat,
353*8975f5c5SAndroid Build Coastguard Worker size_t level,
354*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &destOffset,
355*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
356*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *source)
357*8975f5c5SAndroid Build Coastguard Worker {
358*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
359*8975f5c5SAndroid Build Coastguard Worker
360*8975f5c5SAndroid Build Coastguard Worker BlitProgram *blitProgram = nullptr;
361*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getBlitProgram(context, gl::TextureType::_2D, GL_FLOAT, GL_FLOAT, &blitProgram));
362*8975f5c5SAndroid Build Coastguard Worker
363*8975f5c5SAndroid Build Coastguard Worker // Blit the framebuffer to the first scratch texture
364*8975f5c5SAndroid Build Coastguard Worker const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
365*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
366*8975f5c5SAndroid Build Coastguard Worker
367*8975f5c5SAndroid Build Coastguard Worker GLenum readFormat = source->getImplementationColorReadFormat(context);
368*8975f5c5SAndroid Build Coastguard Worker GLenum readType = source->getImplementationColorReadType(context);
369*8975f5c5SAndroid Build Coastguard Worker
370*8975f5c5SAndroid Build Coastguard Worker // getImplementationColorReadType aligns the type with ES client version
371*8975f5c5SAndroid Build Coastguard Worker if (readType == GL_HALF_FLOAT_OES && mFunctions->standard == STANDARD_GL_DESKTOP)
372*8975f5c5SAndroid Build Coastguard Worker {
373*8975f5c5SAndroid Build Coastguard Worker readType = GL_HALF_FLOAT;
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker
376*8975f5c5SAndroid Build Coastguard Worker nativegl::CopyTexImageImageFormat copyTexImageFormat =
377*8975f5c5SAndroid Build Coastguard Worker nativegl::GetCopyTexImageImageFormat(mFunctions, mFeatures, readFormat, readType);
378*8975f5c5SAndroid Build Coastguard Worker
379*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(gl::TextureType::_2D, mScratchTextures[0]);
380*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY_ALWAYS_CHECK(
381*8975f5c5SAndroid Build Coastguard Worker context, mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat,
382*8975f5c5SAndroid Build Coastguard Worker sourceArea.x, sourceArea.y, sourceArea.width,
383*8975f5c5SAndroid Build Coastguard Worker sourceArea.height, 0));
384*8975f5c5SAndroid Build Coastguard Worker
385*8975f5c5SAndroid Build Coastguard Worker // Set the swizzle of the scratch texture so that the channels sample into the correct emulated
386*8975f5c5SAndroid Build Coastguard Worker // LUMA channels.
387*8975f5c5SAndroid Build Coastguard Worker GLint swizzle[4] = {
388*8975f5c5SAndroid Build Coastguard Worker (lumaFormat == GL_ALPHA) ? GL_ALPHA : GL_RED,
389*8975f5c5SAndroid Build Coastguard Worker (lumaFormat == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO,
390*8975f5c5SAndroid Build Coastguard Worker GL_ZERO,
391*8975f5c5SAndroid Build Coastguard Worker GL_ZERO,
392*8975f5c5SAndroid Build Coastguard Worker };
393*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
394*8975f5c5SAndroid Build Coastguard Worker mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle));
395*8975f5c5SAndroid Build Coastguard Worker
396*8975f5c5SAndroid Build Coastguard Worker // Make a temporary framebuffer using the second scratch texture to render the swizzled result
397*8975f5c5SAndroid Build Coastguard Worker // to.
398*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(gl::TextureType::_2D, mScratchTextures[1]);
399*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY_ALWAYS_CHECK(
400*8975f5c5SAndroid Build Coastguard Worker context, mFunctions->texImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat,
401*8975f5c5SAndroid Build Coastguard Worker sourceArea.width, sourceArea.height, 0,
402*8975f5c5SAndroid Build Coastguard Worker gl::GetUnsizedFormat(copyTexImageFormat.internalFormat),
403*8975f5c5SAndroid Build Coastguard Worker readType, nullptr));
404*8975f5c5SAndroid Build Coastguard Worker
405*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
406*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
407*8975f5c5SAndroid Build Coastguard Worker GL_TEXTURE_2D, mScratchTextures[1], 0));
408*8975f5c5SAndroid Build Coastguard Worker
409*8975f5c5SAndroid Build Coastguard Worker // Render to the destination texture, sampling from the scratch texture
410*8975f5c5SAndroid Build Coastguard Worker ScopedGLState scopedState;
411*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.enter(context, gl::Rectangle(0, 0, sourceArea.width, sourceArea.height)));
412*8975f5c5SAndroid Build Coastguard Worker scopedState.willUseTextureUnit(context, 0);
413*8975f5c5SAndroid Build Coastguard Worker
414*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setScratchTextureParameter(context, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
415*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setScratchTextureParameter(context, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
416*8975f5c5SAndroid Build Coastguard Worker
417*8975f5c5SAndroid Build Coastguard Worker mStateManager->activeTexture(0);
418*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(gl::TextureType::_2D, mScratchTextures[0]);
419*8975f5c5SAndroid Build Coastguard Worker
420*8975f5c5SAndroid Build Coastguard Worker mStateManager->useProgram(blitProgram->program);
421*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->sourceTextureLocation, 0));
422*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform2f(blitProgram->scaleLocation, 1.0, 1.0));
423*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform2f(blitProgram->offsetLocation, 0.0, 0.0));
424*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->multiplyAlphaLocation, 0));
425*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->unMultiplyAlphaLocation, 0));
426*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->transformLinearToSrgbLocation, 0));
427*8975f5c5SAndroid Build Coastguard Worker
428*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setVAOState(context));
429*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
430*8975f5c5SAndroid Build Coastguard Worker
431*8975f5c5SAndroid Build Coastguard Worker // Copy the swizzled texture to the destination texture
432*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(textureType, texture);
433*8975f5c5SAndroid Build Coastguard Worker
434*8975f5c5SAndroid Build Coastguard Worker if (nativegl::UseTexImage3D(textureType))
435*8975f5c5SAndroid Build Coastguard Worker {
436*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
437*8975f5c5SAndroid Build Coastguard Worker mFunctions->copyTexSubImage3D(ToGLenum(target), static_cast<GLint>(level),
438*8975f5c5SAndroid Build Coastguard Worker destOffset.x, destOffset.y, destOffset.z, 0, 0,
439*8975f5c5SAndroid Build Coastguard Worker sourceArea.width, sourceArea.height));
440*8975f5c5SAndroid Build Coastguard Worker }
441*8975f5c5SAndroid Build Coastguard Worker else
442*8975f5c5SAndroid Build Coastguard Worker {
443*8975f5c5SAndroid Build Coastguard Worker ASSERT(nativegl::UseTexImage2D(textureType));
444*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->copyTexSubImage2D(
445*8975f5c5SAndroid Build Coastguard Worker ToGLenum(target), static_cast<GLint>(level), destOffset.x,
446*8975f5c5SAndroid Build Coastguard Worker destOffset.y, 0, 0, sourceArea.width, sourceArea.height));
447*8975f5c5SAndroid Build Coastguard Worker }
448*8975f5c5SAndroid Build Coastguard Worker
449*8975f5c5SAndroid Build Coastguard Worker // Finally orphan the scratch textures so they can be GCed by the driver.
450*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(orphanScratchTextures(context));
451*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, mFunctions, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
452*8975f5c5SAndroid Build Coastguard Worker
453*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.exit(context));
454*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
455*8975f5c5SAndroid Build Coastguard Worker }
456*8975f5c5SAndroid Build Coastguard Worker
blitColorBufferWithShader(const gl::Context * context,const gl::Framebuffer * source,const GLuint destTexture,const gl::TextureTarget destTarget,const size_t destLevel,const gl::Rectangle & sourceAreaIn,const gl::Rectangle & destAreaIn,GLenum filter,bool writeAlpha)457*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::blitColorBufferWithShader(const gl::Context *context,
458*8975f5c5SAndroid Build Coastguard Worker const gl::Framebuffer *source,
459*8975f5c5SAndroid Build Coastguard Worker const GLuint destTexture,
460*8975f5c5SAndroid Build Coastguard Worker const gl::TextureTarget destTarget,
461*8975f5c5SAndroid Build Coastguard Worker const size_t destLevel,
462*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceAreaIn,
463*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &destAreaIn,
464*8975f5c5SAndroid Build Coastguard Worker GLenum filter,
465*8975f5c5SAndroid Build Coastguard Worker bool writeAlpha)
466*8975f5c5SAndroid Build Coastguard Worker {
467*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
468*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
469*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
470*8975f5c5SAndroid Build Coastguard Worker ToGLenum(destTarget), destTexture,
471*8975f5c5SAndroid Build Coastguard Worker static_cast<GLint>(destLevel)));
472*8975f5c5SAndroid Build Coastguard Worker GLenum status = ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
473*8975f5c5SAndroid Build Coastguard Worker if (status != GL_FRAMEBUFFER_COMPLETE)
474*8975f5c5SAndroid Build Coastguard Worker {
475*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
476*8975f5c5SAndroid Build Coastguard Worker }
477*8975f5c5SAndroid Build Coastguard Worker angle::Result result = blitColorBufferWithShader(context, source, mScratchFBO, sourceAreaIn,
478*8975f5c5SAndroid Build Coastguard Worker destAreaIn, filter, writeAlpha);
479*8975f5c5SAndroid Build Coastguard Worker // Unbind the texture from the the scratch framebuffer.
480*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, mFunctions, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
481*8975f5c5SAndroid Build Coastguard Worker return result;
482*8975f5c5SAndroid Build Coastguard Worker }
483*8975f5c5SAndroid Build Coastguard Worker
blitColorBufferWithShader(const gl::Context * context,const gl::Framebuffer * source,const gl::Framebuffer * dest,const gl::Rectangle & sourceAreaIn,const gl::Rectangle & destAreaIn,GLenum filter,bool writeAlpha)484*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::blitColorBufferWithShader(const gl::Context *context,
485*8975f5c5SAndroid Build Coastguard Worker const gl::Framebuffer *source,
486*8975f5c5SAndroid Build Coastguard Worker const gl::Framebuffer *dest,
487*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceAreaIn,
488*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &destAreaIn,
489*8975f5c5SAndroid Build Coastguard Worker GLenum filter,
490*8975f5c5SAndroid Build Coastguard Worker bool writeAlpha)
491*8975f5c5SAndroid Build Coastguard Worker {
492*8975f5c5SAndroid Build Coastguard Worker const FramebufferGL *destGL = GetImplAs<FramebufferGL>(dest);
493*8975f5c5SAndroid Build Coastguard Worker return blitColorBufferWithShader(context, source, destGL->getFramebufferID(), sourceAreaIn,
494*8975f5c5SAndroid Build Coastguard Worker destAreaIn, filter, writeAlpha);
495*8975f5c5SAndroid Build Coastguard Worker }
496*8975f5c5SAndroid Build Coastguard Worker
blitColorBufferWithShader(const gl::Context * context,const gl::Framebuffer * source,const GLuint destFramebuffer,const gl::Rectangle & sourceAreaIn,const gl::Rectangle & destAreaIn,GLenum filter,bool writeAlpha)497*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::blitColorBufferWithShader(const gl::Context *context,
498*8975f5c5SAndroid Build Coastguard Worker const gl::Framebuffer *source,
499*8975f5c5SAndroid Build Coastguard Worker const GLuint destFramebuffer,
500*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceAreaIn,
501*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &destAreaIn,
502*8975f5c5SAndroid Build Coastguard Worker GLenum filter,
503*8975f5c5SAndroid Build Coastguard Worker bool writeAlpha)
504*8975f5c5SAndroid Build Coastguard Worker {
505*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
506*8975f5c5SAndroid Build Coastguard Worker
507*8975f5c5SAndroid Build Coastguard Worker BlitProgram *blitProgram = nullptr;
508*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getBlitProgram(context, gl::TextureType::_2D, GL_FLOAT, GL_FLOAT, &blitProgram));
509*8975f5c5SAndroid Build Coastguard Worker
510*8975f5c5SAndroid Build Coastguard Worker // We'll keep things simple by removing reversed coordinates from the rectangles. In the end
511*8975f5c5SAndroid Build Coastguard Worker // we'll apply the reversal to the source texture coordinates if needed. The destination
512*8975f5c5SAndroid Build Coastguard Worker // rectangle will be set to the gl viewport, which can't be reversed.
513*8975f5c5SAndroid Build Coastguard Worker bool reverseX = sourceAreaIn.isReversedX() != destAreaIn.isReversedX();
514*8975f5c5SAndroid Build Coastguard Worker bool reverseY = sourceAreaIn.isReversedY() != destAreaIn.isReversedY();
515*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle sourceArea = sourceAreaIn.removeReversal();
516*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle destArea = destAreaIn.removeReversal();
517*8975f5c5SAndroid Build Coastguard Worker
518*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *readAttachment = source->getReadColorAttachment();
519*8975f5c5SAndroid Build Coastguard Worker ASSERT(readAttachment->getSamples() <= 1);
520*8975f5c5SAndroid Build Coastguard Worker
521*8975f5c5SAndroid Build Coastguard Worker // Compute the part of the source that will be sampled.
522*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle inBoundsSource;
523*8975f5c5SAndroid Build Coastguard Worker {
524*8975f5c5SAndroid Build Coastguard Worker gl::Extents sourceSize = readAttachment->getSize();
525*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle sourceBounds(0, 0, sourceSize.width, sourceSize.height);
526*8975f5c5SAndroid Build Coastguard Worker if (!gl::ClipRectangle(sourceArea, sourceBounds, &inBoundsSource))
527*8975f5c5SAndroid Build Coastguard Worker {
528*8975f5c5SAndroid Build Coastguard Worker // Early out when the sampled part is empty as the blit will be a noop,
529*8975f5c5SAndroid Build Coastguard Worker // and it prevents a division by zero in later computations.
530*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
531*8975f5c5SAndroid Build Coastguard Worker }
532*8975f5c5SAndroid Build Coastguard Worker }
533*8975f5c5SAndroid Build Coastguard Worker
534*8975f5c5SAndroid Build Coastguard Worker // The blit will be emulated by getting the source of the blit in a texture and sampling it
535*8975f5c5SAndroid Build Coastguard Worker // with CLAMP_TO_EDGE.
536*8975f5c5SAndroid Build Coastguard Worker
537*8975f5c5SAndroid Build Coastguard Worker GLuint textureId;
538*8975f5c5SAndroid Build Coastguard Worker
539*8975f5c5SAndroid Build Coastguard Worker // TODO(cwallez) once texture dirty bits are landed, reuse attached texture instead of using
540*8975f5c5SAndroid Build Coastguard Worker // CopyTexImage2D
541*8975f5c5SAndroid Build Coastguard Worker {
542*8975f5c5SAndroid Build Coastguard Worker textureId = mScratchTextures[0];
543*8975f5c5SAndroid Build Coastguard Worker
544*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &sourceInternalFormat = *readAttachment->getFormat().info;
545*8975f5c5SAndroid Build Coastguard Worker nativegl::CopyTexImageImageFormat copyTexImageFormat = nativegl::GetCopyTexImageImageFormat(
546*8975f5c5SAndroid Build Coastguard Worker mFunctions, mFeatures, sourceInternalFormat.internalFormat, sourceInternalFormat.type);
547*8975f5c5SAndroid Build Coastguard Worker const FramebufferGL *sourceGL = GetImplAs<FramebufferGL>(source);
548*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceGL->getFramebufferID());
549*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(gl::TextureType::_2D, textureId);
550*8975f5c5SAndroid Build Coastguard Worker
551*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY_ALWAYS_CHECK(
552*8975f5c5SAndroid Build Coastguard Worker context, mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat,
553*8975f5c5SAndroid Build Coastguard Worker inBoundsSource.x, inBoundsSource.y,
554*8975f5c5SAndroid Build Coastguard Worker inBoundsSource.width, inBoundsSource.height, 0));
555*8975f5c5SAndroid Build Coastguard Worker
556*8975f5c5SAndroid Build Coastguard Worker // Translate sourceArea to be relative to the copied image.
557*8975f5c5SAndroid Build Coastguard Worker sourceArea.x -= inBoundsSource.x;
558*8975f5c5SAndroid Build Coastguard Worker sourceArea.y -= inBoundsSource.y;
559*8975f5c5SAndroid Build Coastguard Worker
560*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setScratchTextureParameter(context, GL_TEXTURE_MIN_FILTER, filter));
561*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setScratchTextureParameter(context, GL_TEXTURE_MAG_FILTER, filter));
562*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setScratchTextureParameter(context, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
563*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setScratchTextureParameter(context, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
564*8975f5c5SAndroid Build Coastguard Worker }
565*8975f5c5SAndroid Build Coastguard Worker
566*8975f5c5SAndroid Build Coastguard Worker // Transform the source area to the texture coordinate space (where 0.0 and 1.0 correspond to
567*8975f5c5SAndroid Build Coastguard Worker // the edges of the texture).
568*8975f5c5SAndroid Build Coastguard Worker Vector2 texCoordOffset(
569*8975f5c5SAndroid Build Coastguard Worker static_cast<float>(sourceArea.x) / static_cast<float>(inBoundsSource.width),
570*8975f5c5SAndroid Build Coastguard Worker static_cast<float>(sourceArea.y) / static_cast<float>(inBoundsSource.height));
571*8975f5c5SAndroid Build Coastguard Worker // texCoordScale is equal to the size of the source area in texture coordinates.
572*8975f5c5SAndroid Build Coastguard Worker Vector2 texCoordScale(
573*8975f5c5SAndroid Build Coastguard Worker static_cast<float>(sourceArea.width) / static_cast<float>(inBoundsSource.width),
574*8975f5c5SAndroid Build Coastguard Worker static_cast<float>(sourceArea.height) / static_cast<float>(inBoundsSource.height));
575*8975f5c5SAndroid Build Coastguard Worker
576*8975f5c5SAndroid Build Coastguard Worker if (reverseX)
577*8975f5c5SAndroid Build Coastguard Worker {
578*8975f5c5SAndroid Build Coastguard Worker texCoordOffset.x() = texCoordOffset.x() + texCoordScale.x();
579*8975f5c5SAndroid Build Coastguard Worker texCoordScale.x() = -texCoordScale.x();
580*8975f5c5SAndroid Build Coastguard Worker }
581*8975f5c5SAndroid Build Coastguard Worker if (reverseY)
582*8975f5c5SAndroid Build Coastguard Worker {
583*8975f5c5SAndroid Build Coastguard Worker texCoordOffset.y() = texCoordOffset.y() + texCoordScale.y();
584*8975f5c5SAndroid Build Coastguard Worker texCoordScale.y() = -texCoordScale.y();
585*8975f5c5SAndroid Build Coastguard Worker }
586*8975f5c5SAndroid Build Coastguard Worker
587*8975f5c5SAndroid Build Coastguard Worker // Reset all the state except scissor and use the viewport to draw exactly to the destination
588*8975f5c5SAndroid Build Coastguard Worker // rectangle
589*8975f5c5SAndroid Build Coastguard Worker ScopedGLState scopedState;
590*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.enter(context, destArea, ScopedGLState::KEEP_SCISSOR));
591*8975f5c5SAndroid Build Coastguard Worker scopedState.willUseTextureUnit(context, 0);
592*8975f5c5SAndroid Build Coastguard Worker
593*8975f5c5SAndroid Build Coastguard Worker // Set the write color mask to potentially not write alpha
594*8975f5c5SAndroid Build Coastguard Worker mStateManager->setColorMask(true, true, true, writeAlpha);
595*8975f5c5SAndroid Build Coastguard Worker
596*8975f5c5SAndroid Build Coastguard Worker // Set uniforms
597*8975f5c5SAndroid Build Coastguard Worker mStateManager->activeTexture(0);
598*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(gl::TextureType::_2D, textureId);
599*8975f5c5SAndroid Build Coastguard Worker
600*8975f5c5SAndroid Build Coastguard Worker mStateManager->useProgram(blitProgram->program);
601*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->sourceTextureLocation, 0));
602*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform2f(blitProgram->scaleLocation, texCoordScale.x(),
603*8975f5c5SAndroid Build Coastguard Worker texCoordScale.y()));
604*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform2f(blitProgram->offsetLocation, texCoordOffset.x(),
605*8975f5c5SAndroid Build Coastguard Worker texCoordOffset.y()));
606*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->multiplyAlphaLocation, 0));
607*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->unMultiplyAlphaLocation, 0));
608*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->transformLinearToSrgbLocation, 0));
609*8975f5c5SAndroid Build Coastguard Worker
610*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, destFramebuffer);
611*8975f5c5SAndroid Build Coastguard Worker
612*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setVAOState(context));
613*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
614*8975f5c5SAndroid Build Coastguard Worker
615*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.exit(context));
616*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
617*8975f5c5SAndroid Build Coastguard Worker }
618*8975f5c5SAndroid Build Coastguard Worker
copySubTexture(const gl::Context * context,TextureGL * source,size_t sourceLevel,GLenum sourceComponentType,GLuint destID,gl::TextureTarget destTarget,size_t destLevel,GLenum destComponentType,const gl::Extents & sourceSize,const gl::Rectangle & sourceArea,const gl::Offset & destOffset,bool needsLumaWorkaround,GLenum lumaFormat,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,bool transformLinearToSrgb,bool * copySucceededOut)619*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::copySubTexture(const gl::Context *context,
620*8975f5c5SAndroid Build Coastguard Worker TextureGL *source,
621*8975f5c5SAndroid Build Coastguard Worker size_t sourceLevel,
622*8975f5c5SAndroid Build Coastguard Worker GLenum sourceComponentType,
623*8975f5c5SAndroid Build Coastguard Worker GLuint destID,
624*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget destTarget,
625*8975f5c5SAndroid Build Coastguard Worker size_t destLevel,
626*8975f5c5SAndroid Build Coastguard Worker GLenum destComponentType,
627*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &sourceSize,
628*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
629*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &destOffset,
630*8975f5c5SAndroid Build Coastguard Worker bool needsLumaWorkaround,
631*8975f5c5SAndroid Build Coastguard Worker GLenum lumaFormat,
632*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
633*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
634*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha,
635*8975f5c5SAndroid Build Coastguard Worker bool transformLinearToSrgb,
636*8975f5c5SAndroid Build Coastguard Worker bool *copySucceededOut)
637*8975f5c5SAndroid Build Coastguard Worker {
638*8975f5c5SAndroid Build Coastguard Worker ASSERT(source->getType() == gl::TextureType::_2D ||
639*8975f5c5SAndroid Build Coastguard Worker source->getType() == gl::TextureType::External ||
640*8975f5c5SAndroid Build Coastguard Worker source->getType() == gl::TextureType::Rectangle);
641*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
642*8975f5c5SAndroid Build Coastguard Worker
643*8975f5c5SAndroid Build Coastguard Worker // Make sure the destination texture can be rendered to before setting anything else up. Some
644*8975f5c5SAndroid Build Coastguard Worker // cube maps may not be renderable until all faces have been filled.
645*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
646*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
647*8975f5c5SAndroid Build Coastguard Worker ToGLenum(destTarget), destID,
648*8975f5c5SAndroid Build Coastguard Worker static_cast<GLint>(destLevel)));
649*8975f5c5SAndroid Build Coastguard Worker GLenum status = ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
650*8975f5c5SAndroid Build Coastguard Worker if (status != GL_FRAMEBUFFER_COMPLETE)
651*8975f5c5SAndroid Build Coastguard Worker {
652*8975f5c5SAndroid Build Coastguard Worker *copySucceededOut = false;
653*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
654*8975f5c5SAndroid Build Coastguard Worker }
655*8975f5c5SAndroid Build Coastguard Worker
656*8975f5c5SAndroid Build Coastguard Worker BlitProgram *blitProgram = nullptr;
657*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getBlitProgram(context, source->getType(), sourceComponentType, destComponentType,
658*8975f5c5SAndroid Build Coastguard Worker &blitProgram));
659*8975f5c5SAndroid Build Coastguard Worker
660*8975f5c5SAndroid Build Coastguard Worker // Setup the source texture
661*8975f5c5SAndroid Build Coastguard Worker if (needsLumaWorkaround)
662*8975f5c5SAndroid Build Coastguard Worker {
663*8975f5c5SAndroid Build Coastguard Worker GLint luminance = (lumaFormat == GL_ALPHA) ? GL_ZERO : GL_RED;
664*8975f5c5SAndroid Build Coastguard Worker
665*8975f5c5SAndroid Build Coastguard Worker GLint alpha = GL_RED;
666*8975f5c5SAndroid Build Coastguard Worker if (lumaFormat == GL_LUMINANCE)
667*8975f5c5SAndroid Build Coastguard Worker {
668*8975f5c5SAndroid Build Coastguard Worker alpha = GL_ONE;
669*8975f5c5SAndroid Build Coastguard Worker }
670*8975f5c5SAndroid Build Coastguard Worker else if (lumaFormat == GL_LUMINANCE_ALPHA)
671*8975f5c5SAndroid Build Coastguard Worker {
672*8975f5c5SAndroid Build Coastguard Worker alpha = GL_GREEN;
673*8975f5c5SAndroid Build Coastguard Worker }
674*8975f5c5SAndroid Build Coastguard Worker else
675*8975f5c5SAndroid Build Coastguard Worker {
676*8975f5c5SAndroid Build Coastguard Worker ASSERT(lumaFormat == GL_ALPHA);
677*8975f5c5SAndroid Build Coastguard Worker }
678*8975f5c5SAndroid Build Coastguard Worker
679*8975f5c5SAndroid Build Coastguard Worker GLint swizzle[4] = {luminance, luminance, luminance, alpha};
680*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setSwizzle(context, swizzle));
681*8975f5c5SAndroid Build Coastguard Worker }
682*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setMinFilter(context, GL_NEAREST));
683*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setMagFilter(context, GL_NEAREST));
684*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setBaseLevel(context, static_cast<GLuint>(sourceLevel)));
685*8975f5c5SAndroid Build Coastguard Worker
686*8975f5c5SAndroid Build Coastguard Worker // Render to the destination texture, sampling from the source texture
687*8975f5c5SAndroid Build Coastguard Worker ScopedGLState scopedState;
688*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.enter(
689*8975f5c5SAndroid Build Coastguard Worker context, gl::Rectangle(destOffset.x, destOffset.y, sourceArea.width, sourceArea.height)));
690*8975f5c5SAndroid Build Coastguard Worker scopedState.willUseTextureUnit(context, 0);
691*8975f5c5SAndroid Build Coastguard Worker
692*8975f5c5SAndroid Build Coastguard Worker mStateManager->activeTexture(0);
693*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(source->getType(), source->getTextureID());
694*8975f5c5SAndroid Build Coastguard Worker
695*8975f5c5SAndroid Build Coastguard Worker Vector2 scale(sourceArea.width, sourceArea.height);
696*8975f5c5SAndroid Build Coastguard Worker Vector2 offset(sourceArea.x, sourceArea.y);
697*8975f5c5SAndroid Build Coastguard Worker if (source->getType() != gl::TextureType::Rectangle)
698*8975f5c5SAndroid Build Coastguard Worker {
699*8975f5c5SAndroid Build Coastguard Worker scale.x() /= static_cast<float>(sourceSize.width);
700*8975f5c5SAndroid Build Coastguard Worker scale.y() /= static_cast<float>(sourceSize.height);
701*8975f5c5SAndroid Build Coastguard Worker offset.x() /= static_cast<float>(sourceSize.width);
702*8975f5c5SAndroid Build Coastguard Worker offset.y() /= static_cast<float>(sourceSize.height);
703*8975f5c5SAndroid Build Coastguard Worker }
704*8975f5c5SAndroid Build Coastguard Worker if (unpackFlipY)
705*8975f5c5SAndroid Build Coastguard Worker {
706*8975f5c5SAndroid Build Coastguard Worker offset.y() += scale.y();
707*8975f5c5SAndroid Build Coastguard Worker scale.y() = -scale.y();
708*8975f5c5SAndroid Build Coastguard Worker }
709*8975f5c5SAndroid Build Coastguard Worker
710*8975f5c5SAndroid Build Coastguard Worker mStateManager->useProgram(blitProgram->program);
711*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->sourceTextureLocation, 0));
712*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform2f(blitProgram->scaleLocation, scale.x(), scale.y()));
713*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
714*8975f5c5SAndroid Build Coastguard Worker mFunctions->uniform2f(blitProgram->offsetLocation, offset.x(), offset.y()));
715*8975f5c5SAndroid Build Coastguard Worker if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
716*8975f5c5SAndroid Build Coastguard Worker {
717*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->multiplyAlphaLocation, 0));
718*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->unMultiplyAlphaLocation, 0));
719*8975f5c5SAndroid Build Coastguard Worker }
720*8975f5c5SAndroid Build Coastguard Worker else
721*8975f5c5SAndroid Build Coastguard Worker {
722*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->multiplyAlphaLocation,
723*8975f5c5SAndroid Build Coastguard Worker unpackPremultiplyAlpha));
724*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->unMultiplyAlphaLocation,
725*8975f5c5SAndroid Build Coastguard Worker unpackUnmultiplyAlpha));
726*8975f5c5SAndroid Build Coastguard Worker }
727*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->transformLinearToSrgbLocation,
728*8975f5c5SAndroid Build Coastguard Worker transformLinearToSrgb));
729*8975f5c5SAndroid Build Coastguard Worker
730*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setVAOState(context));
731*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
732*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, mFunctions, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
733*8975f5c5SAndroid Build Coastguard Worker
734*8975f5c5SAndroid Build Coastguard Worker *copySucceededOut = true;
735*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.exit(context));
736*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
737*8975f5c5SAndroid Build Coastguard Worker }
738*8975f5c5SAndroid Build Coastguard Worker
copySubTextureCPUReadback(const gl::Context * context,TextureGL * source,size_t sourceLevel,GLenum sourceSizedInternalFormat,TextureGL * dest,gl::TextureTarget destTarget,size_t destLevel,GLenum destFormat,GLenum destType,const gl::Extents & sourceSize,const gl::Rectangle & sourceArea,const gl::Offset & destOffset,bool needsLumaWorkaround,GLenum lumaFormat,bool unpackFlipY,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)739*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::copySubTextureCPUReadback(const gl::Context *context,
740*8975f5c5SAndroid Build Coastguard Worker TextureGL *source,
741*8975f5c5SAndroid Build Coastguard Worker size_t sourceLevel,
742*8975f5c5SAndroid Build Coastguard Worker GLenum sourceSizedInternalFormat,
743*8975f5c5SAndroid Build Coastguard Worker TextureGL *dest,
744*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget destTarget,
745*8975f5c5SAndroid Build Coastguard Worker size_t destLevel,
746*8975f5c5SAndroid Build Coastguard Worker GLenum destFormat,
747*8975f5c5SAndroid Build Coastguard Worker GLenum destType,
748*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &sourceSize,
749*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
750*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &destOffset,
751*8975f5c5SAndroid Build Coastguard Worker bool needsLumaWorkaround,
752*8975f5c5SAndroid Build Coastguard Worker GLenum lumaFormat,
753*8975f5c5SAndroid Build Coastguard Worker bool unpackFlipY,
754*8975f5c5SAndroid Build Coastguard Worker bool unpackPremultiplyAlpha,
755*8975f5c5SAndroid Build Coastguard Worker bool unpackUnmultiplyAlpha)
756*8975f5c5SAndroid Build Coastguard Worker {
757*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
758*8975f5c5SAndroid Build Coastguard Worker
759*8975f5c5SAndroid Build Coastguard Worker ContextGL *contextGL = GetImplAs<ContextGL>(context);
760*8975f5c5SAndroid Build Coastguard Worker
761*8975f5c5SAndroid Build Coastguard Worker ASSERT(source->getType() == gl::TextureType::_2D ||
762*8975f5c5SAndroid Build Coastguard Worker source->getType() == gl::TextureType::External ||
763*8975f5c5SAndroid Build Coastguard Worker source->getType() == gl::TextureType::Rectangle);
764*8975f5c5SAndroid Build Coastguard Worker const auto &destInternalFormatInfo = gl::GetInternalFormatInfo(destFormat, destType);
765*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &sourceInternalFormatInfo =
766*8975f5c5SAndroid Build Coastguard Worker gl::GetSizedInternalFormatInfo(sourceSizedInternalFormat);
767*8975f5c5SAndroid Build Coastguard Worker
768*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle readPixelsArea = sourceArea;
769*8975f5c5SAndroid Build Coastguard Worker
770*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
771*8975f5c5SAndroid Build Coastguard Worker bool supportExternalTarget =
772*8975f5c5SAndroid Build Coastguard Worker source->getType() == gl::TextureType::External && context->getExtensions().YUVTargetEXT;
773*8975f5c5SAndroid Build Coastguard Worker GLenum status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
774*8975f5c5SAndroid Build Coastguard Worker if (supportExternalTarget || source->getType() != gl::TextureType::External)
775*8975f5c5SAndroid Build Coastguard Worker {
776*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(
777*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ToGLenum(source->getType()),
778*8975f5c5SAndroid Build Coastguard Worker source->getTextureID(), static_cast<GLint>(sourceLevel)));
779*8975f5c5SAndroid Build Coastguard Worker status = ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
780*8975f5c5SAndroid Build Coastguard Worker }
781*8975f5c5SAndroid Build Coastguard Worker if (status != GL_FRAMEBUFFER_COMPLETE)
782*8975f5c5SAndroid Build Coastguard Worker {
783*8975f5c5SAndroid Build Coastguard Worker // The source texture cannot be read with glReadPixels. Copy it into another RGBA texture
784*8975f5c5SAndroid Build Coastguard Worker // and read that back instead.
785*8975f5c5SAndroid Build Coastguard Worker nativegl::TexImageFormat texImageFormat = nativegl::GetTexImageFormat(
786*8975f5c5SAndroid Build Coastguard Worker mFunctions, mFeatures, sourceInternalFormatInfo.internalFormat,
787*8975f5c5SAndroid Build Coastguard Worker sourceInternalFormatInfo.format, sourceInternalFormatInfo.type);
788*8975f5c5SAndroid Build Coastguard Worker
789*8975f5c5SAndroid Build Coastguard Worker gl::TextureType scratchTextureType = gl::TextureType::_2D;
790*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(scratchTextureType, mScratchTextures[0]);
791*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY_ALWAYS_CHECK(
792*8975f5c5SAndroid Build Coastguard Worker context,
793*8975f5c5SAndroid Build Coastguard Worker mFunctions->texImage2D(ToGLenum(scratchTextureType), 0, texImageFormat.internalFormat,
794*8975f5c5SAndroid Build Coastguard Worker sourceArea.width, sourceArea.height, 0, texImageFormat.format,
795*8975f5c5SAndroid Build Coastguard Worker texImageFormat.type, nullptr));
796*8975f5c5SAndroid Build Coastguard Worker
797*8975f5c5SAndroid Build Coastguard Worker bool copySucceeded = false;
798*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(copySubTexture(
799*8975f5c5SAndroid Build Coastguard Worker context, source, sourceLevel, sourceInternalFormatInfo.componentType,
800*8975f5c5SAndroid Build Coastguard Worker mScratchTextures[0], NonCubeTextureTypeToTarget(scratchTextureType), 0,
801*8975f5c5SAndroid Build Coastguard Worker sourceInternalFormatInfo.componentType, sourceSize, sourceArea, gl::Offset(0, 0, 0),
802*8975f5c5SAndroid Build Coastguard Worker needsLumaWorkaround, lumaFormat, false, false, false, false, ©Succeeded));
803*8975f5c5SAndroid Build Coastguard Worker if (!copySucceeded)
804*8975f5c5SAndroid Build Coastguard Worker {
805*8975f5c5SAndroid Build Coastguard Worker // No fallback options if we can't render to the scratch texture.
806*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Stop;
807*8975f5c5SAndroid Build Coastguard Worker }
808*8975f5c5SAndroid Build Coastguard Worker
809*8975f5c5SAndroid Build Coastguard Worker // Bind the scratch texture as the readback texture
810*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
811*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
812*8975f5c5SAndroid Build Coastguard Worker ToGLenum(scratchTextureType),
813*8975f5c5SAndroid Build Coastguard Worker mScratchTextures[0], 0));
814*8975f5c5SAndroid Build Coastguard Worker
815*8975f5c5SAndroid Build Coastguard Worker // The scratch texture sized to sourceArea so adjust the readpixels area
816*8975f5c5SAndroid Build Coastguard Worker readPixelsArea.x = 0;
817*8975f5c5SAndroid Build Coastguard Worker readPixelsArea.y = 0;
818*8975f5c5SAndroid Build Coastguard Worker
819*8975f5c5SAndroid Build Coastguard Worker // Recheck the status
820*8975f5c5SAndroid Build Coastguard Worker status = ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
821*8975f5c5SAndroid Build Coastguard Worker }
822*8975f5c5SAndroid Build Coastguard Worker
823*8975f5c5SAndroid Build Coastguard Worker ASSERT(status == GL_FRAMEBUFFER_COMPLETE);
824*8975f5c5SAndroid Build Coastguard Worker
825*8975f5c5SAndroid Build Coastguard Worker // Create a buffer for holding the source and destination memory
826*8975f5c5SAndroid Build Coastguard Worker const size_t sourcePixelSize = 4;
827*8975f5c5SAndroid Build Coastguard Worker size_t sourceBufferSize = readPixelsArea.width * readPixelsArea.height * sourcePixelSize;
828*8975f5c5SAndroid Build Coastguard Worker size_t destBufferSize =
829*8975f5c5SAndroid Build Coastguard Worker readPixelsArea.width * readPixelsArea.height * destInternalFormatInfo.pixelBytes;
830*8975f5c5SAndroid Build Coastguard Worker angle::MemoryBuffer *buffer = nullptr;
831*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK_GL_ALLOC(contextGL,
832*8975f5c5SAndroid Build Coastguard Worker context->getScratchBuffer(sourceBufferSize + destBufferSize, &buffer));
833*8975f5c5SAndroid Build Coastguard Worker
834*8975f5c5SAndroid Build Coastguard Worker uint8_t *sourceMemory = buffer->data();
835*8975f5c5SAndroid Build Coastguard Worker uint8_t *destMemory = buffer->data() + sourceBufferSize;
836*8975f5c5SAndroid Build Coastguard Worker
837*8975f5c5SAndroid Build Coastguard Worker GLenum readPixelsFormat = GL_NONE;
838*8975f5c5SAndroid Build Coastguard Worker PixelReadFunction readFunction = nullptr;
839*8975f5c5SAndroid Build Coastguard Worker if (sourceInternalFormatInfo.componentType == GL_UNSIGNED_INT)
840*8975f5c5SAndroid Build Coastguard Worker {
841*8975f5c5SAndroid Build Coastguard Worker readPixelsFormat = GL_RGBA_INTEGER;
842*8975f5c5SAndroid Build Coastguard Worker readFunction = angle::ReadColor<angle::R8G8B8A8, GLuint>;
843*8975f5c5SAndroid Build Coastguard Worker }
844*8975f5c5SAndroid Build Coastguard Worker else
845*8975f5c5SAndroid Build Coastguard Worker {
846*8975f5c5SAndroid Build Coastguard Worker ASSERT(sourceInternalFormatInfo.componentType != GL_INT);
847*8975f5c5SAndroid Build Coastguard Worker readPixelsFormat = GL_RGBA;
848*8975f5c5SAndroid Build Coastguard Worker readFunction = angle::ReadColor<angle::R8G8B8A8, GLfloat>;
849*8975f5c5SAndroid Build Coastguard Worker }
850*8975f5c5SAndroid Build Coastguard Worker
851*8975f5c5SAndroid Build Coastguard Worker gl::PixelUnpackState unpack;
852*8975f5c5SAndroid Build Coastguard Worker unpack.alignment = 1;
853*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelUnpackState(context, unpack));
854*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelUnpackBuffer(context, nullptr));
855*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->readPixels(readPixelsArea.x, readPixelsArea.y,
856*8975f5c5SAndroid Build Coastguard Worker readPixelsArea.width, readPixelsArea.height,
857*8975f5c5SAndroid Build Coastguard Worker readPixelsFormat, GL_UNSIGNED_BYTE, sourceMemory));
858*8975f5c5SAndroid Build Coastguard Worker
859*8975f5c5SAndroid Build Coastguard Worker angle::FormatID destFormatID =
860*8975f5c5SAndroid Build Coastguard Worker angle::Format::InternalFormatToID(destInternalFormatInfo.sizedInternalFormat);
861*8975f5c5SAndroid Build Coastguard Worker const auto &destFormatInfo = angle::Format::Get(destFormatID);
862*8975f5c5SAndroid Build Coastguard Worker CopyImageCHROMIUM(
863*8975f5c5SAndroid Build Coastguard Worker sourceMemory, readPixelsArea.width * sourcePixelSize, sourcePixelSize, 0, readFunction,
864*8975f5c5SAndroid Build Coastguard Worker destMemory, readPixelsArea.width * destInternalFormatInfo.pixelBytes,
865*8975f5c5SAndroid Build Coastguard Worker destInternalFormatInfo.pixelBytes, 0, destFormatInfo.pixelWriteFunction,
866*8975f5c5SAndroid Build Coastguard Worker destInternalFormatInfo.format, destInternalFormatInfo.componentType, readPixelsArea.width,
867*8975f5c5SAndroid Build Coastguard Worker readPixelsArea.height, 1, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
868*8975f5c5SAndroid Build Coastguard Worker
869*8975f5c5SAndroid Build Coastguard Worker gl::PixelPackState pack;
870*8975f5c5SAndroid Build Coastguard Worker pack.alignment = 1;
871*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelPackState(context, pack));
872*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelPackBuffer(context, nullptr));
873*8975f5c5SAndroid Build Coastguard Worker
874*8975f5c5SAndroid Build Coastguard Worker nativegl::TexSubImageFormat texSubImageFormat =
875*8975f5c5SAndroid Build Coastguard Worker nativegl::GetTexSubImageFormat(mFunctions, mFeatures, destFormat, destType);
876*8975f5c5SAndroid Build Coastguard Worker
877*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(dest->getType(), dest->getTextureID());
878*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texSubImage2D(
879*8975f5c5SAndroid Build Coastguard Worker ToGLenum(destTarget), static_cast<GLint>(destLevel), destOffset.x,
880*8975f5c5SAndroid Build Coastguard Worker destOffset.y, readPixelsArea.width, readPixelsArea.height,
881*8975f5c5SAndroid Build Coastguard Worker texSubImageFormat.format, texSubImageFormat.type, destMemory));
882*8975f5c5SAndroid Build Coastguard Worker
883*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, mFunctions, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
884*8975f5c5SAndroid Build Coastguard Worker
885*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
886*8975f5c5SAndroid Build Coastguard Worker }
887*8975f5c5SAndroid Build Coastguard Worker
copyTexSubImage(const gl::Context * context,TextureGL * source,size_t sourceLevel,TextureGL * dest,gl::TextureTarget destTarget,size_t destLevel,const gl::Rectangle & sourceArea,const gl::Offset & destOffset,bool * copySucceededOut)888*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::copyTexSubImage(const gl::Context *context,
889*8975f5c5SAndroid Build Coastguard Worker TextureGL *source,
890*8975f5c5SAndroid Build Coastguard Worker size_t sourceLevel,
891*8975f5c5SAndroid Build Coastguard Worker TextureGL *dest,
892*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget destTarget,
893*8975f5c5SAndroid Build Coastguard Worker size_t destLevel,
894*8975f5c5SAndroid Build Coastguard Worker const gl::Rectangle &sourceArea,
895*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &destOffset,
896*8975f5c5SAndroid Build Coastguard Worker bool *copySucceededOut)
897*8975f5c5SAndroid Build Coastguard Worker {
898*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
899*8975f5c5SAndroid Build Coastguard Worker
900*8975f5c5SAndroid Build Coastguard Worker // Make sure the source texture can create a complete framebuffer before continuing.
901*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
902*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(
903*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ToGLenum(source->getType()),
904*8975f5c5SAndroid Build Coastguard Worker source->getTextureID(), static_cast<GLint>(sourceLevel)));
905*8975f5c5SAndroid Build Coastguard Worker GLenum status = ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
906*8975f5c5SAndroid Build Coastguard Worker if (status != GL_FRAMEBUFFER_COMPLETE)
907*8975f5c5SAndroid Build Coastguard Worker {
908*8975f5c5SAndroid Build Coastguard Worker *copySucceededOut = false;
909*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
910*8975f5c5SAndroid Build Coastguard Worker }
911*8975f5c5SAndroid Build Coastguard Worker
912*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(dest->getType(), dest->getTextureID());
913*8975f5c5SAndroid Build Coastguard Worker
914*8975f5c5SAndroid Build Coastguard Worker // Handle GL errors during copyTexSubImage2D manually since this can fail for certain formats on
915*8975f5c5SAndroid Build Coastguard Worker // Pixel 2 and 4 and we have fallback paths (blit via shader) in the caller.
916*8975f5c5SAndroid Build Coastguard Worker ClearErrors(context, __FILE__, __FUNCTION__, __LINE__);
917*8975f5c5SAndroid Build Coastguard Worker mFunctions->copyTexSubImage2D(ToGLenum(destTarget), static_cast<GLint>(destLevel), destOffset.x,
918*8975f5c5SAndroid Build Coastguard Worker destOffset.y, sourceArea.x, sourceArea.y, sourceArea.width,
919*8975f5c5SAndroid Build Coastguard Worker sourceArea.height);
920*8975f5c5SAndroid Build Coastguard Worker // Use getError to retrieve the error directly instead of using CheckError so that we don't
921*8975f5c5SAndroid Build Coastguard Worker // propagate the error to the client and also so that we can handle INVALID_OPERATION specially.
922*8975f5c5SAndroid Build Coastguard Worker const GLenum copyError = mFunctions->getError();
923*8975f5c5SAndroid Build Coastguard Worker // Any error other than NO_ERROR or INVALID_OPERATION is propagated to the client as a failure.
924*8975f5c5SAndroid Build Coastguard Worker // INVALID_OPERATION is ignored and instead copySucceeded is set to false so that the caller can
925*8975f5c5SAndroid Build Coastguard Worker // fallback to another copy/blit implementation.
926*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(copyError != GL_NO_ERROR && copyError != GL_INVALID_OPERATION))
927*8975f5c5SAndroid Build Coastguard Worker {
928*8975f5c5SAndroid Build Coastguard Worker // Propagate the error to the client and check for other unexpected errors.
929*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
930*8975f5c5SAndroid Build Coastguard Worker HandleError(context, copyError, "copyTexSubImage2D", __FILE__, __FUNCTION__, __LINE__));
931*8975f5c5SAndroid Build Coastguard Worker }
932*8975f5c5SAndroid Build Coastguard Worker // Even if copyTexSubImage2D fails with GL_INVALID_OPERATION, check for other unexpected errors.
933*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CheckError(context, "copyTexSubImage2D", __FILE__, __FUNCTION__, __LINE__));
934*8975f5c5SAndroid Build Coastguard Worker
935*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, mFunctions, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
936*8975f5c5SAndroid Build Coastguard Worker *copySucceededOut = copyError == GL_NO_ERROR;
937*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
938*8975f5c5SAndroid Build Coastguard Worker }
939*8975f5c5SAndroid Build Coastguard Worker
clearRenderableTexture(const gl::Context * context,TextureGL * source,GLenum sizedInternalFormat,int numTextureLayers,const gl::ImageIndex & imageIndex,bool * clearSucceededOut)940*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::clearRenderableTexture(const gl::Context *context,
941*8975f5c5SAndroid Build Coastguard Worker TextureGL *source,
942*8975f5c5SAndroid Build Coastguard Worker GLenum sizedInternalFormat,
943*8975f5c5SAndroid Build Coastguard Worker int numTextureLayers,
944*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex,
945*8975f5c5SAndroid Build Coastguard Worker bool *clearSucceededOut)
946*8975f5c5SAndroid Build Coastguard Worker {
947*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
948*8975f5c5SAndroid Build Coastguard Worker
949*8975f5c5SAndroid Build Coastguard Worker ClearBindTargetVector bindTargets;
950*8975f5c5SAndroid Build Coastguard Worker ClearBindTargetVector unbindTargets;
951*8975f5c5SAndroid Build Coastguard Worker GLbitfield clearMask = 0;
952*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(PrepareForClear(mStateManager, sizedInternalFormat, &bindTargets, &unbindTargets,
953*8975f5c5SAndroid Build Coastguard Worker &clearMask));
954*8975f5c5SAndroid Build Coastguard Worker
955*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
956*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachments(context, mFunctions, GL_FRAMEBUFFER, unbindTargets));
957*8975f5c5SAndroid Build Coastguard Worker
958*8975f5c5SAndroid Build Coastguard Worker if (nativegl::UseTexImage2D(source->getType()))
959*8975f5c5SAndroid Build Coastguard Worker {
960*8975f5c5SAndroid Build Coastguard Worker ASSERT(numTextureLayers == 1);
961*8975f5c5SAndroid Build Coastguard Worker for (GLenum bindTarget : bindTargets)
962*8975f5c5SAndroid Build Coastguard Worker {
963*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(
964*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER, bindTarget, ToGLenum(imageIndex.getTarget()),
965*8975f5c5SAndroid Build Coastguard Worker source->getTextureID(), imageIndex.getLevelIndex()));
966*8975f5c5SAndroid Build Coastguard Worker }
967*8975f5c5SAndroid Build Coastguard Worker
968*8975f5c5SAndroid Build Coastguard Worker GLenum status = ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
969*8975f5c5SAndroid Build Coastguard Worker if (status == GL_FRAMEBUFFER_COMPLETE)
970*8975f5c5SAndroid Build Coastguard Worker {
971*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->clear(clearMask));
972*8975f5c5SAndroid Build Coastguard Worker }
973*8975f5c5SAndroid Build Coastguard Worker else
974*8975f5c5SAndroid Build Coastguard Worker {
975*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachments(context, mFunctions, GL_FRAMEBUFFER, bindTargets));
976*8975f5c5SAndroid Build Coastguard Worker *clearSucceededOut = false;
977*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
978*8975f5c5SAndroid Build Coastguard Worker }
979*8975f5c5SAndroid Build Coastguard Worker }
980*8975f5c5SAndroid Build Coastguard Worker else
981*8975f5c5SAndroid Build Coastguard Worker {
982*8975f5c5SAndroid Build Coastguard Worker ASSERT(nativegl::UseTexImage3D(source->getType()));
983*8975f5c5SAndroid Build Coastguard Worker
984*8975f5c5SAndroid Build Coastguard Worker // Check if it's possible to bind all layers of the texture at once
985*8975f5c5SAndroid Build Coastguard Worker if (mFunctions->framebufferTexture && !imageIndex.hasLayer())
986*8975f5c5SAndroid Build Coastguard Worker {
987*8975f5c5SAndroid Build Coastguard Worker for (GLenum bindTarget : bindTargets)
988*8975f5c5SAndroid Build Coastguard Worker {
989*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture(GL_FRAMEBUFFER, bindTarget,
990*8975f5c5SAndroid Build Coastguard Worker source->getTextureID(),
991*8975f5c5SAndroid Build Coastguard Worker imageIndex.getLevelIndex()));
992*8975f5c5SAndroid Build Coastguard Worker }
993*8975f5c5SAndroid Build Coastguard Worker
994*8975f5c5SAndroid Build Coastguard Worker GLenum status =
995*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
996*8975f5c5SAndroid Build Coastguard Worker if (status == GL_FRAMEBUFFER_COMPLETE)
997*8975f5c5SAndroid Build Coastguard Worker {
998*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->clear(clearMask));
999*8975f5c5SAndroid Build Coastguard Worker }
1000*8975f5c5SAndroid Build Coastguard Worker else
1001*8975f5c5SAndroid Build Coastguard Worker {
1002*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachments(context, mFunctions, GL_FRAMEBUFFER, bindTargets));
1003*8975f5c5SAndroid Build Coastguard Worker *clearSucceededOut = false;
1004*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1005*8975f5c5SAndroid Build Coastguard Worker }
1006*8975f5c5SAndroid Build Coastguard Worker }
1007*8975f5c5SAndroid Build Coastguard Worker else
1008*8975f5c5SAndroid Build Coastguard Worker {
1009*8975f5c5SAndroid Build Coastguard Worker GLint firstLayer = 0;
1010*8975f5c5SAndroid Build Coastguard Worker GLint layerCount = numTextureLayers;
1011*8975f5c5SAndroid Build Coastguard Worker if (imageIndex.hasLayer())
1012*8975f5c5SAndroid Build Coastguard Worker {
1013*8975f5c5SAndroid Build Coastguard Worker firstLayer = imageIndex.getLayerIndex();
1014*8975f5c5SAndroid Build Coastguard Worker layerCount = imageIndex.getLayerCount();
1015*8975f5c5SAndroid Build Coastguard Worker }
1016*8975f5c5SAndroid Build Coastguard Worker
1017*8975f5c5SAndroid Build Coastguard Worker for (GLint layer = 0; layer < layerCount; layer++)
1018*8975f5c5SAndroid Build Coastguard Worker {
1019*8975f5c5SAndroid Build Coastguard Worker for (GLenum bindTarget : bindTargets)
1020*8975f5c5SAndroid Build Coastguard Worker {
1021*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTextureLayer(
1022*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER, bindTarget, source->getTextureID(),
1023*8975f5c5SAndroid Build Coastguard Worker imageIndex.getLevelIndex(), layer + firstLayer));
1024*8975f5c5SAndroid Build Coastguard Worker }
1025*8975f5c5SAndroid Build Coastguard Worker
1026*8975f5c5SAndroid Build Coastguard Worker GLenum status =
1027*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER));
1028*8975f5c5SAndroid Build Coastguard Worker if (status == GL_FRAMEBUFFER_COMPLETE)
1029*8975f5c5SAndroid Build Coastguard Worker {
1030*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->clear(clearMask));
1031*8975f5c5SAndroid Build Coastguard Worker }
1032*8975f5c5SAndroid Build Coastguard Worker else
1033*8975f5c5SAndroid Build Coastguard Worker {
1034*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachments(context, mFunctions, GL_FRAMEBUFFER, bindTargets));
1035*8975f5c5SAndroid Build Coastguard Worker *clearSucceededOut = false;
1036*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1037*8975f5c5SAndroid Build Coastguard Worker }
1038*8975f5c5SAndroid Build Coastguard Worker }
1039*8975f5c5SAndroid Build Coastguard Worker }
1040*8975f5c5SAndroid Build Coastguard Worker }
1041*8975f5c5SAndroid Build Coastguard Worker
1042*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachments(context, mFunctions, GL_FRAMEBUFFER, bindTargets));
1043*8975f5c5SAndroid Build Coastguard Worker *clearSucceededOut = true;
1044*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1045*8975f5c5SAndroid Build Coastguard Worker }
1046*8975f5c5SAndroid Build Coastguard Worker
clearRenderbuffer(const gl::Context * context,RenderbufferGL * source,GLenum sizedInternalFormat)1047*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::clearRenderbuffer(const gl::Context *context,
1048*8975f5c5SAndroid Build Coastguard Worker RenderbufferGL *source,
1049*8975f5c5SAndroid Build Coastguard Worker GLenum sizedInternalFormat)
1050*8975f5c5SAndroid Build Coastguard Worker {
1051*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
1052*8975f5c5SAndroid Build Coastguard Worker
1053*8975f5c5SAndroid Build Coastguard Worker ClearBindTargetVector bindTargets;
1054*8975f5c5SAndroid Build Coastguard Worker ClearBindTargetVector unbindTargets;
1055*8975f5c5SAndroid Build Coastguard Worker GLbitfield clearMask = 0;
1056*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(PrepareForClear(mStateManager, sizedInternalFormat, &bindTargets, &unbindTargets,
1057*8975f5c5SAndroid Build Coastguard Worker &clearMask));
1058*8975f5c5SAndroid Build Coastguard Worker
1059*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
1060*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachments(context, mFunctions, GL_FRAMEBUFFER, unbindTargets));
1061*8975f5c5SAndroid Build Coastguard Worker
1062*8975f5c5SAndroid Build Coastguard Worker for (GLenum bindTarget : bindTargets)
1063*8975f5c5SAndroid Build Coastguard Worker {
1064*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1065*8975f5c5SAndroid Build Coastguard Worker mFunctions->framebufferRenderbuffer(
1066*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER, bindTarget, GL_RENDERBUFFER, source->getRenderbufferID()));
1067*8975f5c5SAndroid Build Coastguard Worker }
1068*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->clear(clearMask));
1069*8975f5c5SAndroid Build Coastguard Worker
1070*8975f5c5SAndroid Build Coastguard Worker // Unbind
1071*8975f5c5SAndroid Build Coastguard Worker for (GLenum bindTarget : bindTargets)
1072*8975f5c5SAndroid Build Coastguard Worker {
1073*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferRenderbuffer(GL_FRAMEBUFFER, bindTarget,
1074*8975f5c5SAndroid Build Coastguard Worker GL_RENDERBUFFER, 0));
1075*8975f5c5SAndroid Build Coastguard Worker }
1076*8975f5c5SAndroid Build Coastguard Worker
1077*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1078*8975f5c5SAndroid Build Coastguard Worker }
1079*8975f5c5SAndroid Build Coastguard Worker
clearFramebuffer(const gl::Context * context,const gl::DrawBufferMask & colorAttachments,bool depthClear,bool stencilClear,FramebufferGL * source)1080*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::clearFramebuffer(const gl::Context *context,
1081*8975f5c5SAndroid Build Coastguard Worker const gl::DrawBufferMask &colorAttachments,
1082*8975f5c5SAndroid Build Coastguard Worker bool depthClear,
1083*8975f5c5SAndroid Build Coastguard Worker bool stencilClear,
1084*8975f5c5SAndroid Build Coastguard Worker FramebufferGL *source)
1085*8975f5c5SAndroid Build Coastguard Worker {
1086*8975f5c5SAndroid Build Coastguard Worker // initializeResources skipped because no local state is used
1087*8975f5c5SAndroid Build Coastguard Worker
1088*8975f5c5SAndroid Build Coastguard Worker bool hasIntegerColorAttachments = false;
1089*8975f5c5SAndroid Build Coastguard Worker
1090*8975f5c5SAndroid Build Coastguard Worker // Filter the color attachments for ones that actually have an init state of uninitialized.
1091*8975f5c5SAndroid Build Coastguard Worker gl::DrawBufferMask uninitializedColorAttachments;
1092*8975f5c5SAndroid Build Coastguard Worker for (size_t colorAttachmentIdx : colorAttachments)
1093*8975f5c5SAndroid Build Coastguard Worker {
1094*8975f5c5SAndroid Build Coastguard Worker bool needsInit = false;
1095*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *attachment =
1096*8975f5c5SAndroid Build Coastguard Worker source->getState().getColorAttachment(colorAttachmentIdx);
1097*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CheckIfAttachmentNeedsClearing(context, attachment, &needsInit));
1098*8975f5c5SAndroid Build Coastguard Worker uninitializedColorAttachments[colorAttachmentIdx] = needsInit;
1099*8975f5c5SAndroid Build Coastguard Worker if (needsInit && (attachment->getComponentType() == GL_INT ||
1100*8975f5c5SAndroid Build Coastguard Worker attachment->getComponentType() == GL_UNSIGNED_INT))
1101*8975f5c5SAndroid Build Coastguard Worker {
1102*8975f5c5SAndroid Build Coastguard Worker hasIntegerColorAttachments = true;
1103*8975f5c5SAndroid Build Coastguard Worker }
1104*8975f5c5SAndroid Build Coastguard Worker }
1105*8975f5c5SAndroid Build Coastguard Worker
1106*8975f5c5SAndroid Build Coastguard Worker bool depthNeedsInit = false;
1107*8975f5c5SAndroid Build Coastguard Worker if (depthClear)
1108*8975f5c5SAndroid Build Coastguard Worker {
1109*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CheckIfAttachmentNeedsClearing(context, source->getState().getDepthAttachment(),
1110*8975f5c5SAndroid Build Coastguard Worker &depthNeedsInit));
1111*8975f5c5SAndroid Build Coastguard Worker }
1112*8975f5c5SAndroid Build Coastguard Worker
1113*8975f5c5SAndroid Build Coastguard Worker bool stencilNeedsInit = false;
1114*8975f5c5SAndroid Build Coastguard Worker if (stencilClear)
1115*8975f5c5SAndroid Build Coastguard Worker {
1116*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CheckIfAttachmentNeedsClearing(context, source->getState().getStencilAttachment(),
1117*8975f5c5SAndroid Build Coastguard Worker &stencilNeedsInit));
1118*8975f5c5SAndroid Build Coastguard Worker }
1119*8975f5c5SAndroid Build Coastguard Worker
1120*8975f5c5SAndroid Build Coastguard Worker // Clear all attachments
1121*8975f5c5SAndroid Build Coastguard Worker GLbitfield clearMask = 0;
1122*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(SetClearState(mStateManager, uninitializedColorAttachments.any(), depthNeedsInit,
1123*8975f5c5SAndroid Build Coastguard Worker stencilNeedsInit, &clearMask));
1124*8975f5c5SAndroid Build Coastguard Worker
1125*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, source->getFramebufferID());
1126*8975f5c5SAndroid Build Coastguard Worker
1127*8975f5c5SAndroid Build Coastguard Worker // If we're not clearing all attached color attachments, we need to clear them individually with
1128*8975f5c5SAndroid Build Coastguard Worker // glClearBuffer*
1129*8975f5c5SAndroid Build Coastguard Worker if ((clearMask & GL_COLOR_BUFFER_BIT) &&
1130*8975f5c5SAndroid Build Coastguard Worker (uninitializedColorAttachments != source->getState().getColorAttachmentsMask() ||
1131*8975f5c5SAndroid Build Coastguard Worker uninitializedColorAttachments != source->getState().getEnabledDrawBuffers() ||
1132*8975f5c5SAndroid Build Coastguard Worker hasIntegerColorAttachments))
1133*8975f5c5SAndroid Build Coastguard Worker {
1134*8975f5c5SAndroid Build Coastguard Worker for (size_t colorAttachmentIdx : uninitializedColorAttachments)
1135*8975f5c5SAndroid Build Coastguard Worker {
1136*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment *attachment =
1137*8975f5c5SAndroid Build Coastguard Worker source->getState().getColorAttachment(colorAttachmentIdx);
1138*8975f5c5SAndroid Build Coastguard Worker if (attachment->initState() == gl::InitState::Initialized)
1139*8975f5c5SAndroid Build Coastguard Worker {
1140*8975f5c5SAndroid Build Coastguard Worker continue;
1141*8975f5c5SAndroid Build Coastguard Worker }
1142*8975f5c5SAndroid Build Coastguard Worker
1143*8975f5c5SAndroid Build Coastguard Worker switch (attachment->getComponentType())
1144*8975f5c5SAndroid Build Coastguard Worker {
1145*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_NORMALIZED:
1146*8975f5c5SAndroid Build Coastguard Worker case GL_SIGNED_NORMALIZED:
1147*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT:
1148*8975f5c5SAndroid Build Coastguard Worker {
1149*8975f5c5SAndroid Build Coastguard Worker constexpr GLfloat clearValue[] = {0, 0, 0, 0};
1150*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1151*8975f5c5SAndroid Build Coastguard Worker mFunctions->clearBufferfv(
1152*8975f5c5SAndroid Build Coastguard Worker GL_COLOR, static_cast<GLint>(colorAttachmentIdx), clearValue));
1153*8975f5c5SAndroid Build Coastguard Worker }
1154*8975f5c5SAndroid Build Coastguard Worker break;
1155*8975f5c5SAndroid Build Coastguard Worker
1156*8975f5c5SAndroid Build Coastguard Worker case GL_INT:
1157*8975f5c5SAndroid Build Coastguard Worker {
1158*8975f5c5SAndroid Build Coastguard Worker constexpr GLint clearValue[] = {0, 0, 0, 0};
1159*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1160*8975f5c5SAndroid Build Coastguard Worker mFunctions->clearBufferiv(
1161*8975f5c5SAndroid Build Coastguard Worker GL_COLOR, static_cast<GLint>(colorAttachmentIdx), clearValue));
1162*8975f5c5SAndroid Build Coastguard Worker }
1163*8975f5c5SAndroid Build Coastguard Worker break;
1164*8975f5c5SAndroid Build Coastguard Worker
1165*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
1166*8975f5c5SAndroid Build Coastguard Worker {
1167*8975f5c5SAndroid Build Coastguard Worker constexpr GLuint clearValue[] = {0, 0, 0, 0};
1168*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1169*8975f5c5SAndroid Build Coastguard Worker mFunctions->clearBufferuiv(
1170*8975f5c5SAndroid Build Coastguard Worker GL_COLOR, static_cast<GLint>(colorAttachmentIdx), clearValue));
1171*8975f5c5SAndroid Build Coastguard Worker }
1172*8975f5c5SAndroid Build Coastguard Worker break;
1173*8975f5c5SAndroid Build Coastguard Worker
1174*8975f5c5SAndroid Build Coastguard Worker default:
1175*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1176*8975f5c5SAndroid Build Coastguard Worker break;
1177*8975f5c5SAndroid Build Coastguard Worker }
1178*8975f5c5SAndroid Build Coastguard Worker }
1179*8975f5c5SAndroid Build Coastguard Worker
1180*8975f5c5SAndroid Build Coastguard Worker // Remove color buffer bit and clear the rest of the attachments with glClear
1181*8975f5c5SAndroid Build Coastguard Worker clearMask = clearMask & ~GL_COLOR_BUFFER_BIT;
1182*8975f5c5SAndroid Build Coastguard Worker }
1183*8975f5c5SAndroid Build Coastguard Worker
1184*8975f5c5SAndroid Build Coastguard Worker if (clearMask != 0)
1185*8975f5c5SAndroid Build Coastguard Worker {
1186*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->clear(clearMask));
1187*8975f5c5SAndroid Build Coastguard Worker }
1188*8975f5c5SAndroid Build Coastguard Worker
1189*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1190*8975f5c5SAndroid Build Coastguard Worker }
1191*8975f5c5SAndroid Build Coastguard Worker
clearRenderableTextureAlphaToOne(const gl::Context * context,GLuint texture,gl::TextureTarget target,size_t level)1192*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::clearRenderableTextureAlphaToOne(const gl::Context *context,
1193*8975f5c5SAndroid Build Coastguard Worker GLuint texture,
1194*8975f5c5SAndroid Build Coastguard Worker gl::TextureTarget target,
1195*8975f5c5SAndroid Build Coastguard Worker size_t level)
1196*8975f5c5SAndroid Build Coastguard Worker {
1197*8975f5c5SAndroid Build Coastguard Worker // Clearing the alpha of 3D textures is not supported/needed yet.
1198*8975f5c5SAndroid Build Coastguard Worker ASSERT(nativegl::UseTexImage2D(TextureTargetToType(target)));
1199*8975f5c5SAndroid Build Coastguard Worker
1200*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
1201*8975f5c5SAndroid Build Coastguard Worker
1202*8975f5c5SAndroid Build Coastguard Worker mStateManager->setClearColor(gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f));
1203*8975f5c5SAndroid Build Coastguard Worker mStateManager->setColorMask(false, false, false, true);
1204*8975f5c5SAndroid Build Coastguard Worker mStateManager->setScissorTestEnabled(false);
1205*8975f5c5SAndroid Build Coastguard Worker
1206*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
1207*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1208*8975f5c5SAndroid Build Coastguard Worker ToGLenum(target), texture,
1209*8975f5c5SAndroid Build Coastguard Worker static_cast<GLint>(level)));
1210*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->clear(GL_COLOR_BUFFER_BIT));
1211*8975f5c5SAndroid Build Coastguard Worker
1212*8975f5c5SAndroid Build Coastguard Worker // Unbind the texture from the the scratch framebuffer
1213*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, mFunctions, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
1214*8975f5c5SAndroid Build Coastguard Worker
1215*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1216*8975f5c5SAndroid Build Coastguard Worker }
1217*8975f5c5SAndroid Build Coastguard Worker
generateMipmap(const gl::Context * context,TextureGL * source,GLuint baseLevel,GLuint levelCount,const gl::Extents & sourceBaseLevelSize,const nativegl::TexImageFormat & format)1218*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::generateMipmap(const gl::Context *context,
1219*8975f5c5SAndroid Build Coastguard Worker TextureGL *source,
1220*8975f5c5SAndroid Build Coastguard Worker GLuint baseLevel,
1221*8975f5c5SAndroid Build Coastguard Worker GLuint levelCount,
1222*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &sourceBaseLevelSize,
1223*8975f5c5SAndroid Build Coastguard Worker const nativegl::TexImageFormat &format)
1224*8975f5c5SAndroid Build Coastguard Worker {
1225*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeResources(context));
1226*8975f5c5SAndroid Build Coastguard Worker
1227*8975f5c5SAndroid Build Coastguard Worker const gl::TextureType sourceType = gl::TextureType::_2D;
1228*8975f5c5SAndroid Build Coastguard Worker const gl::TextureTarget sourceTarget = gl::TextureTarget::_2D;
1229*8975f5c5SAndroid Build Coastguard Worker
1230*8975f5c5SAndroid Build Coastguard Worker ScopedGLState scopedState;
1231*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.enter(
1232*8975f5c5SAndroid Build Coastguard Worker context, gl::Rectangle(0, 0, sourceBaseLevelSize.width, sourceBaseLevelSize.height)));
1233*8975f5c5SAndroid Build Coastguard Worker scopedState.willUseTextureUnit(context, 0);
1234*8975f5c5SAndroid Build Coastguard Worker mStateManager->activeTexture(0);
1235*8975f5c5SAndroid Build Coastguard Worker
1236*8975f5c5SAndroid Build Coastguard Worker // Copy source to an intermediate texture.
1237*8975f5c5SAndroid Build Coastguard Worker GLuint intermediateTexture = mScratchTextures[0];
1238*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(sourceType, intermediateTexture);
1239*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindBuffer(gl::BufferBinding::PixelUnpack, 0);
1240*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteri(ToGLenum(sourceTarget), GL_TEXTURE_MIN_FILTER,
1241*8975f5c5SAndroid Build Coastguard Worker GL_NEAREST));
1242*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteri(ToGLenum(sourceTarget), GL_TEXTURE_MAG_FILTER,
1243*8975f5c5SAndroid Build Coastguard Worker GL_NEAREST));
1244*8975f5c5SAndroid Build Coastguard Worker
1245*8975f5c5SAndroid Build Coastguard Worker // Use a shader to copy the source to intermediate texture. glBlitFramebuffer does not always do
1246*8975f5c5SAndroid Build Coastguard Worker // sRGB to linear conversions for us.
1247*8975f5c5SAndroid Build Coastguard Worker BlitProgram *blitProgram = nullptr;
1248*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getBlitProgram(context, sourceType, GL_FLOAT, GL_FLOAT, &blitProgram));
1249*8975f5c5SAndroid Build Coastguard Worker
1250*8975f5c5SAndroid Build Coastguard Worker mStateManager->useProgram(blitProgram->program);
1251*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->sourceTextureLocation, 0));
1252*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform2f(blitProgram->scaleLocation, 1.0f, 1.0f));
1253*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform2f(blitProgram->offsetLocation, 0.0f, 0.0f));
1254*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->multiplyAlphaLocation, 0));
1255*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->unMultiplyAlphaLocation, 0));
1256*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->uniform1i(blitProgram->transformLinearToSrgbLocation, 0));
1257*8975f5c5SAndroid Build Coastguard Worker
1258*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
1259*8975f5c5SAndroid Build Coastguard Worker mStateManager->setFramebufferSRGBEnabled(context, true);
1260*8975f5c5SAndroid Build Coastguard Worker
1261*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setVAOState(context));
1262*8975f5c5SAndroid Build Coastguard Worker
1263*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setMinFilter(context, GL_LINEAR));
1264*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setMagFilter(context, GL_LINEAR));
1265*8975f5c5SAndroid Build Coastguard Worker
1266*8975f5c5SAndroid Build Coastguard Worker // Copy back to the source texture from the mips generated in the intermediate texture
1267*8975f5c5SAndroid Build Coastguard Worker for (GLuint levelIdx = 1; levelIdx < levelCount; levelIdx++)
1268*8975f5c5SAndroid Build Coastguard Worker {
1269*8975f5c5SAndroid Build Coastguard Worker gl::Extents levelSize(std::max(sourceBaseLevelSize.width >> levelIdx, 1),
1270*8975f5c5SAndroid Build Coastguard Worker std::max(sourceBaseLevelSize.height >> levelIdx, 1), 1);
1271*8975f5c5SAndroid Build Coastguard Worker
1272*8975f5c5SAndroid Build Coastguard Worker // Downsample from the source texture into the intermediate texture
1273*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(sourceType, intermediateTexture);
1274*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texImage2D(
1275*8975f5c5SAndroid Build Coastguard Worker ToGLenum(sourceTarget), 0, format.internalFormat, levelSize.width,
1276*8975f5c5SAndroid Build Coastguard Worker levelSize.height, 0, format.format, format.type, nullptr));
1277*8975f5c5SAndroid Build Coastguard Worker
1278*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1279*8975f5c5SAndroid Build Coastguard Worker ToGLenum(sourceTarget),
1280*8975f5c5SAndroid Build Coastguard Worker intermediateTexture, 0));
1281*8975f5c5SAndroid Build Coastguard Worker mStateManager->setViewport(gl::Rectangle(0, 0, levelSize.width, levelSize.height));
1282*8975f5c5SAndroid Build Coastguard Worker
1283*8975f5c5SAndroid Build Coastguard Worker GLuint sourceTextureReadLevel = baseLevel + levelIdx - 1;
1284*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(sourceType, source->getTextureID());
1285*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setBaseLevel(context, sourceTextureReadLevel));
1286*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
1287*8975f5c5SAndroid Build Coastguard Worker
1288*8975f5c5SAndroid Build Coastguard Worker // Copy back to the source texture
1289*8975f5c5SAndroid Build Coastguard Worker GLuint sourceTextureWriteLevel = sourceTextureReadLevel + 1;
1290*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->framebufferTexture2D(
1291*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ToGLenum(sourceTarget),
1292*8975f5c5SAndroid Build Coastguard Worker source->getTextureID(), sourceTextureWriteLevel));
1293*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(sourceType, intermediateTexture);
1294*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->drawArrays(GL_TRIANGLES, 0, 3));
1295*8975f5c5SAndroid Build Coastguard Worker }
1296*8975f5c5SAndroid Build Coastguard Worker
1297*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(source->setBaseLevel(context, baseLevel));
1298*8975f5c5SAndroid Build Coastguard Worker
1299*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(orphanScratchTextures(context));
1300*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(UnbindAttachment(context, mFunctions, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0));
1301*8975f5c5SAndroid Build Coastguard Worker
1302*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(scopedState.exit(context));
1303*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1304*8975f5c5SAndroid Build Coastguard Worker }
1305*8975f5c5SAndroid Build Coastguard Worker
generateSRGBMipmap(const gl::Context * context,TextureGL * source,GLuint baseLevel,GLuint levelCount,const gl::Extents & sourceBaseLevelSize)1306*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::generateSRGBMipmap(const gl::Context *context,
1307*8975f5c5SAndroid Build Coastguard Worker TextureGL *source,
1308*8975f5c5SAndroid Build Coastguard Worker GLuint baseLevel,
1309*8975f5c5SAndroid Build Coastguard Worker GLuint levelCount,
1310*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &sourceBaseLevelSize)
1311*8975f5c5SAndroid Build Coastguard Worker {
1312*8975f5c5SAndroid Build Coastguard Worker return generateMipmap(context, source, baseLevel, levelCount, sourceBaseLevelSize,
1313*8975f5c5SAndroid Build Coastguard Worker mSRGBMipmapGenerationFormat);
1314*8975f5c5SAndroid Build Coastguard Worker }
1315*8975f5c5SAndroid Build Coastguard Worker
initializeResources(const gl::Context * context)1316*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::initializeResources(const gl::Context *context)
1317*8975f5c5SAndroid Build Coastguard Worker {
1318*8975f5c5SAndroid Build Coastguard Worker if (mResourcesInitialized)
1319*8975f5c5SAndroid Build Coastguard Worker {
1320*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1321*8975f5c5SAndroid Build Coastguard Worker }
1322*8975f5c5SAndroid Build Coastguard Worker
1323*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
1324*8975f5c5SAndroid Build Coastguard Worker {
1325*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->genTextures(1, &mScratchTextures[i]));
1326*8975f5c5SAndroid Build Coastguard Worker }
1327*8975f5c5SAndroid Build Coastguard Worker
1328*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->genFramebuffers(1, &mScratchFBO));
1329*8975f5c5SAndroid Build Coastguard Worker
1330*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->genBuffers(1, &mVertexBuffer));
1331*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindBuffer(gl::BufferBinding::Array, mVertexBuffer);
1332*8975f5c5SAndroid Build Coastguard Worker
1333*8975f5c5SAndroid Build Coastguard Worker // Use a single, large triangle, to avoid arithmetic precision issues where fragments
1334*8975f5c5SAndroid Build Coastguard Worker // with the same Y coordinate don't get exactly the same interpolated texcoord Y.
1335*8975f5c5SAndroid Build Coastguard Worker float vertexData[] = {
1336*8975f5c5SAndroid Build Coastguard Worker -0.5f, 0.0f, 1.5f, 0.0f, 0.5f, 2.0f,
1337*8975f5c5SAndroid Build Coastguard Worker };
1338*8975f5c5SAndroid Build Coastguard Worker
1339*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->bufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, vertexData,
1340*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW));
1341*8975f5c5SAndroid Build Coastguard Worker
1342*8975f5c5SAndroid Build Coastguard Worker VertexArrayStateGL *defaultVAOState = mStateManager->getDefaultVAOState();
1343*8975f5c5SAndroid Build Coastguard Worker if (!mFeatures.syncAllVertexArraysToDefault.enabled)
1344*8975f5c5SAndroid Build Coastguard Worker {
1345*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->genVertexArrays(1, &mVAO));
1346*8975f5c5SAndroid Build Coastguard Worker mVAOState = new VertexArrayStateGL(defaultVAOState->attributes.size(),
1347*8975f5c5SAndroid Build Coastguard Worker defaultVAOState->bindings.size());
1348*8975f5c5SAndroid Build Coastguard Worker mOwnsVAOState = true;
1349*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(setVAOState(context));
1350*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeVAOState(context));
1351*8975f5c5SAndroid Build Coastguard Worker }
1352*8975f5c5SAndroid Build Coastguard Worker else
1353*8975f5c5SAndroid Build Coastguard Worker {
1354*8975f5c5SAndroid Build Coastguard Worker mVAO = mStateManager->getDefaultVAO();
1355*8975f5c5SAndroid Build Coastguard Worker mVAOState = defaultVAOState;
1356*8975f5c5SAndroid Build Coastguard Worker mOwnsVAOState = false;
1357*8975f5c5SAndroid Build Coastguard Worker }
1358*8975f5c5SAndroid Build Coastguard Worker
1359*8975f5c5SAndroid Build Coastguard Worker constexpr GLenum potentialSRGBMipmapGenerationFormats[] = {
1360*8975f5c5SAndroid Build Coastguard Worker GL_RGBA16, GL_RGBA16F, GL_RGBA32F,
1361*8975f5c5SAndroid Build Coastguard Worker GL_RGBA8, // RGBA8 can have precision loss when generating mipmaps of a sRGBA8 texture
1362*8975f5c5SAndroid Build Coastguard Worker };
1363*8975f5c5SAndroid Build Coastguard Worker for (GLenum internalFormat : potentialSRGBMipmapGenerationFormats)
1364*8975f5c5SAndroid Build Coastguard Worker {
1365*8975f5c5SAndroid Build Coastguard Worker if (nativegl::SupportsNativeRendering(mFunctions, gl::TextureType::_2D, internalFormat))
1366*8975f5c5SAndroid Build Coastguard Worker {
1367*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &internalFormatInfo =
1368*8975f5c5SAndroid Build Coastguard Worker gl::GetSizedInternalFormatInfo(internalFormat);
1369*8975f5c5SAndroid Build Coastguard Worker
1370*8975f5c5SAndroid Build Coastguard Worker // Pass the 'format' instead of 'internalFormat' to make sure we use unsized formats
1371*8975f5c5SAndroid Build Coastguard Worker // when available to increase support.
1372*8975f5c5SAndroid Build Coastguard Worker mSRGBMipmapGenerationFormat =
1373*8975f5c5SAndroid Build Coastguard Worker nativegl::GetTexImageFormat(mFunctions, mFeatures, internalFormatInfo.format,
1374*8975f5c5SAndroid Build Coastguard Worker internalFormatInfo.format, internalFormatInfo.type);
1375*8975f5c5SAndroid Build Coastguard Worker break;
1376*8975f5c5SAndroid Build Coastguard Worker }
1377*8975f5c5SAndroid Build Coastguard Worker }
1378*8975f5c5SAndroid Build Coastguard Worker ASSERT(mSRGBMipmapGenerationFormat.internalFormat != GL_NONE);
1379*8975f5c5SAndroid Build Coastguard Worker
1380*8975f5c5SAndroid Build Coastguard Worker mResourcesInitialized = true;
1381*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1382*8975f5c5SAndroid Build Coastguard Worker }
1383*8975f5c5SAndroid Build Coastguard Worker
orphanScratchTextures(const gl::Context * context)1384*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::orphanScratchTextures(const gl::Context *context)
1385*8975f5c5SAndroid Build Coastguard Worker {
1386*8975f5c5SAndroid Build Coastguard Worker for (auto texture : mScratchTextures)
1387*8975f5c5SAndroid Build Coastguard Worker {
1388*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(gl::TextureType::_2D, texture);
1389*8975f5c5SAndroid Build Coastguard Worker gl::PixelUnpackState unpack;
1390*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelUnpackState(context, unpack));
1391*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStateManager->setPixelUnpackBuffer(context, nullptr));
1392*8975f5c5SAndroid Build Coastguard Worker if (mFunctions->isAtLeastGL(gl::Version(3, 3)))
1393*8975f5c5SAndroid Build Coastguard Worker {
1394*8975f5c5SAndroid Build Coastguard Worker constexpr GLint swizzle[4] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
1395*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA,
1396*8975f5c5SAndroid Build Coastguard Worker swizzle));
1397*8975f5c5SAndroid Build Coastguard Worker }
1398*8975f5c5SAndroid Build Coastguard Worker else if (mFunctions->isAtLeastGLES(gl::Version(3, 0)))
1399*8975f5c5SAndroid Build Coastguard Worker {
1400*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1401*8975f5c5SAndroid Build Coastguard Worker mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED));
1402*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1403*8975f5c5SAndroid Build Coastguard Worker mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN));
1404*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1405*8975f5c5SAndroid Build Coastguard Worker mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE));
1406*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1407*8975f5c5SAndroid Build Coastguard Worker mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA));
1408*8975f5c5SAndroid Build Coastguard Worker }
1409*8975f5c5SAndroid Build Coastguard Worker
1410*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0));
1411*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000));
1412*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1413*8975f5c5SAndroid Build Coastguard Worker GL_NEAREST_MIPMAP_LINEAR));
1414*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context,
1415*8975f5c5SAndroid Build Coastguard Worker mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1416*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA,
1417*8975f5c5SAndroid Build Coastguard Worker GL_UNSIGNED_BYTE, nullptr));
1418*8975f5c5SAndroid Build Coastguard Worker }
1419*8975f5c5SAndroid Build Coastguard Worker
1420*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1421*8975f5c5SAndroid Build Coastguard Worker }
1422*8975f5c5SAndroid Build Coastguard Worker
setScratchTextureParameter(const gl::Context * context,GLenum param,GLenum value)1423*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::setScratchTextureParameter(const gl::Context *context,
1424*8975f5c5SAndroid Build Coastguard Worker GLenum param,
1425*8975f5c5SAndroid Build Coastguard Worker GLenum value)
1426*8975f5c5SAndroid Build Coastguard Worker {
1427*8975f5c5SAndroid Build Coastguard Worker for (auto texture : mScratchTextures)
1428*8975f5c5SAndroid Build Coastguard Worker {
1429*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindTexture(gl::TextureType::_2D, texture);
1430*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteri(GL_TEXTURE_2D, param, value));
1431*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->texParameteri(GL_TEXTURE_2D, param, value));
1432*8975f5c5SAndroid Build Coastguard Worker }
1433*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1434*8975f5c5SAndroid Build Coastguard Worker }
1435*8975f5c5SAndroid Build Coastguard Worker
setVAOState(const gl::Context * context)1436*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::setVAOState(const gl::Context *context)
1437*8975f5c5SAndroid Build Coastguard Worker {
1438*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindVertexArray(mVAO, mVAOState);
1439*8975f5c5SAndroid Build Coastguard Worker if (mFeatures.syncAllVertexArraysToDefault.enabled)
1440*8975f5c5SAndroid Build Coastguard Worker {
1441*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(initializeVAOState(context));
1442*8975f5c5SAndroid Build Coastguard Worker }
1443*8975f5c5SAndroid Build Coastguard Worker
1444*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1445*8975f5c5SAndroid Build Coastguard Worker }
1446*8975f5c5SAndroid Build Coastguard Worker
initializeVAOState(const gl::Context * context)1447*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::initializeVAOState(const gl::Context *context)
1448*8975f5c5SAndroid Build Coastguard Worker {
1449*8975f5c5SAndroid Build Coastguard Worker mStateManager->bindBuffer(gl::BufferBinding::Array, mVertexBuffer);
1450*8975f5c5SAndroid Build Coastguard Worker
1451*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->enableVertexAttribArray(mTexcoordAttribLocation));
1452*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->vertexAttribPointer(mTexcoordAttribLocation, 2, GL_FLOAT,
1453*8975f5c5SAndroid Build Coastguard Worker GL_FALSE, 0, nullptr));
1454*8975f5c5SAndroid Build Coastguard Worker
1455*8975f5c5SAndroid Build Coastguard Worker VertexAttributeGL &attribute = mVAOState->attributes[mTexcoordAttribLocation];
1456*8975f5c5SAndroid Build Coastguard Worker attribute.enabled = true;
1457*8975f5c5SAndroid Build Coastguard Worker attribute.format = &angle::Format::Get(angle::FormatID::R32G32_FLOAT);
1458*8975f5c5SAndroid Build Coastguard Worker attribute.pointer = nullptr;
1459*8975f5c5SAndroid Build Coastguard Worker
1460*8975f5c5SAndroid Build Coastguard Worker VertexBindingGL &binding = mVAOState->bindings[mTexcoordAttribLocation];
1461*8975f5c5SAndroid Build Coastguard Worker binding.stride = 8;
1462*8975f5c5SAndroid Build Coastguard Worker binding.offset = 0;
1463*8975f5c5SAndroid Build Coastguard Worker binding.buffer = mVertexBuffer;
1464*8975f5c5SAndroid Build Coastguard Worker
1465*8975f5c5SAndroid Build Coastguard Worker if (mFeatures.syncAllVertexArraysToDefault.enabled)
1466*8975f5c5SAndroid Build Coastguard Worker {
1467*8975f5c5SAndroid Build Coastguard Worker mStateManager->setDefaultVAOStateDirty();
1468*8975f5c5SAndroid Build Coastguard Worker }
1469*8975f5c5SAndroid Build Coastguard Worker
1470*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1471*8975f5c5SAndroid Build Coastguard Worker }
1472*8975f5c5SAndroid Build Coastguard Worker
getBlitProgram(const gl::Context * context,gl::TextureType sourceTextureType,GLenum sourceComponentType,GLenum destComponentType,BlitProgram ** program)1473*8975f5c5SAndroid Build Coastguard Worker angle::Result BlitGL::getBlitProgram(const gl::Context *context,
1474*8975f5c5SAndroid Build Coastguard Worker gl::TextureType sourceTextureType,
1475*8975f5c5SAndroid Build Coastguard Worker GLenum sourceComponentType,
1476*8975f5c5SAndroid Build Coastguard Worker GLenum destComponentType,
1477*8975f5c5SAndroid Build Coastguard Worker BlitProgram **program)
1478*8975f5c5SAndroid Build Coastguard Worker {
1479*8975f5c5SAndroid Build Coastguard Worker
1480*8975f5c5SAndroid Build Coastguard Worker BlitProgramType programType(sourceTextureType, sourceComponentType, destComponentType);
1481*8975f5c5SAndroid Build Coastguard Worker BlitProgram &result = mBlitPrograms[programType];
1482*8975f5c5SAndroid Build Coastguard Worker if (result.program == 0)
1483*8975f5c5SAndroid Build Coastguard Worker {
1484*8975f5c5SAndroid Build Coastguard Worker result.program = ANGLE_GL_TRY(context, mFunctions->createProgram());
1485*8975f5c5SAndroid Build Coastguard Worker
1486*8975f5c5SAndroid Build Coastguard Worker // Depending on what types need to be output by the shaders, different versions need to be
1487*8975f5c5SAndroid Build Coastguard Worker // used.
1488*8975f5c5SAndroid Build Coastguard Worker constexpr const char *texcoordAttribName = "a_texcoord";
1489*8975f5c5SAndroid Build Coastguard Worker std::string version;
1490*8975f5c5SAndroid Build Coastguard Worker std::string vsInputVariableQualifier;
1491*8975f5c5SAndroid Build Coastguard Worker std::string vsOutputVariableQualifier;
1492*8975f5c5SAndroid Build Coastguard Worker std::string fsInputVariableQualifier;
1493*8975f5c5SAndroid Build Coastguard Worker std::string fsOutputVariableQualifier;
1494*8975f5c5SAndroid Build Coastguard Worker std::string sampleFunction;
1495*8975f5c5SAndroid Build Coastguard Worker if (sourceComponentType != GL_UNSIGNED_INT && destComponentType != GL_UNSIGNED_INT &&
1496*8975f5c5SAndroid Build Coastguard Worker sourceTextureType != gl::TextureType::Rectangle)
1497*8975f5c5SAndroid Build Coastguard Worker {
1498*8975f5c5SAndroid Build Coastguard Worker // Simple case, float-to-float with 2D or external textures. Only needs ESSL/GLSL 100
1499*8975f5c5SAndroid Build Coastguard Worker version = "100";
1500*8975f5c5SAndroid Build Coastguard Worker vsInputVariableQualifier = "attribute";
1501*8975f5c5SAndroid Build Coastguard Worker vsOutputVariableQualifier = "varying";
1502*8975f5c5SAndroid Build Coastguard Worker fsInputVariableQualifier = "varying";
1503*8975f5c5SAndroid Build Coastguard Worker fsOutputVariableQualifier = "";
1504*8975f5c5SAndroid Build Coastguard Worker sampleFunction = "texture2D";
1505*8975f5c5SAndroid Build Coastguard Worker }
1506*8975f5c5SAndroid Build Coastguard Worker else
1507*8975f5c5SAndroid Build Coastguard Worker {
1508*8975f5c5SAndroid Build Coastguard Worker // Need to use a higher version to support non-float output types
1509*8975f5c5SAndroid Build Coastguard Worker if (mFunctions->standard == STANDARD_GL_DESKTOP)
1510*8975f5c5SAndroid Build Coastguard Worker {
1511*8975f5c5SAndroid Build Coastguard Worker version = "330";
1512*8975f5c5SAndroid Build Coastguard Worker }
1513*8975f5c5SAndroid Build Coastguard Worker else
1514*8975f5c5SAndroid Build Coastguard Worker {
1515*8975f5c5SAndroid Build Coastguard Worker ASSERT(mFunctions->standard == STANDARD_GL_ES);
1516*8975f5c5SAndroid Build Coastguard Worker version = "300 es";
1517*8975f5c5SAndroid Build Coastguard Worker }
1518*8975f5c5SAndroid Build Coastguard Worker vsInputVariableQualifier = "in";
1519*8975f5c5SAndroid Build Coastguard Worker vsOutputVariableQualifier = "out";
1520*8975f5c5SAndroid Build Coastguard Worker fsInputVariableQualifier = "in";
1521*8975f5c5SAndroid Build Coastguard Worker fsOutputVariableQualifier = "out";
1522*8975f5c5SAndroid Build Coastguard Worker sampleFunction = "texture";
1523*8975f5c5SAndroid Build Coastguard Worker }
1524*8975f5c5SAndroid Build Coastguard Worker
1525*8975f5c5SAndroid Build Coastguard Worker {
1526*8975f5c5SAndroid Build Coastguard Worker // Compile the vertex shader
1527*8975f5c5SAndroid Build Coastguard Worker std::ostringstream vsSourceStream;
1528*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << "#version " << version << "\n";
1529*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << vsInputVariableQualifier << " vec2 " << texcoordAttribName << ";\n";
1530*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << "uniform vec2 u_scale;\n";
1531*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << "uniform vec2 u_offset;\n";
1532*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << vsOutputVariableQualifier << " vec2 v_texcoord;\n";
1533*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << "\n";
1534*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << "void main()\n";
1535*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << "{\n";
1536*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << " gl_Position = vec4((" << texcoordAttribName
1537*8975f5c5SAndroid Build Coastguard Worker << " * 2.0) - 1.0, 0.0, 1.0);\n";
1538*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << " v_texcoord = " << texcoordAttribName
1539*8975f5c5SAndroid Build Coastguard Worker << " * u_scale + u_offset;\n";
1540*8975f5c5SAndroid Build Coastguard Worker vsSourceStream << "}\n";
1541*8975f5c5SAndroid Build Coastguard Worker
1542*8975f5c5SAndroid Build Coastguard Worker std::string vsSourceStr = vsSourceStream.str();
1543*8975f5c5SAndroid Build Coastguard Worker const char *vsSourceCStr = vsSourceStr.c_str();
1544*8975f5c5SAndroid Build Coastguard Worker
1545*8975f5c5SAndroid Build Coastguard Worker GLuint vs = ANGLE_GL_TRY(context, mFunctions->createShader(GL_VERTEX_SHADER));
1546*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->shaderSource(vs, 1, &vsSourceCStr, nullptr));
1547*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->compileShader(vs));
1548*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CheckCompileStatus(context, mFunctions, vs));
1549*8975f5c5SAndroid Build Coastguard Worker
1550*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->attachShader(result.program, vs));
1551*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->deleteShader(vs));
1552*8975f5c5SAndroid Build Coastguard Worker }
1553*8975f5c5SAndroid Build Coastguard Worker
1554*8975f5c5SAndroid Build Coastguard Worker {
1555*8975f5c5SAndroid Build Coastguard Worker // Sampling texture uniform changes depending on source texture type.
1556*8975f5c5SAndroid Build Coastguard Worker std::string samplerType;
1557*8975f5c5SAndroid Build Coastguard Worker switch (sourceTextureType)
1558*8975f5c5SAndroid Build Coastguard Worker {
1559*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::_2D:
1560*8975f5c5SAndroid Build Coastguard Worker switch (sourceComponentType)
1561*8975f5c5SAndroid Build Coastguard Worker {
1562*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
1563*8975f5c5SAndroid Build Coastguard Worker samplerType = "usampler2D";
1564*8975f5c5SAndroid Build Coastguard Worker break;
1565*8975f5c5SAndroid Build Coastguard Worker
1566*8975f5c5SAndroid Build Coastguard Worker default: // Float type
1567*8975f5c5SAndroid Build Coastguard Worker samplerType = "sampler2D";
1568*8975f5c5SAndroid Build Coastguard Worker break;
1569*8975f5c5SAndroid Build Coastguard Worker }
1570*8975f5c5SAndroid Build Coastguard Worker break;
1571*8975f5c5SAndroid Build Coastguard Worker
1572*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::External:
1573*8975f5c5SAndroid Build Coastguard Worker ASSERT(sourceComponentType != GL_UNSIGNED_INT);
1574*8975f5c5SAndroid Build Coastguard Worker samplerType = "samplerExternalOES";
1575*8975f5c5SAndroid Build Coastguard Worker break;
1576*8975f5c5SAndroid Build Coastguard Worker
1577*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::Rectangle:
1578*8975f5c5SAndroid Build Coastguard Worker ASSERT(sourceComponentType != GL_UNSIGNED_INT);
1579*8975f5c5SAndroid Build Coastguard Worker samplerType = "sampler2DRect";
1580*8975f5c5SAndroid Build Coastguard Worker break;
1581*8975f5c5SAndroid Build Coastguard Worker
1582*8975f5c5SAndroid Build Coastguard Worker default:
1583*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
1584*8975f5c5SAndroid Build Coastguard Worker break;
1585*8975f5c5SAndroid Build Coastguard Worker }
1586*8975f5c5SAndroid Build Coastguard Worker
1587*8975f5c5SAndroid Build Coastguard Worker std::string samplerResultType;
1588*8975f5c5SAndroid Build Coastguard Worker switch (sourceComponentType)
1589*8975f5c5SAndroid Build Coastguard Worker {
1590*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
1591*8975f5c5SAndroid Build Coastguard Worker samplerResultType = "uvec4";
1592*8975f5c5SAndroid Build Coastguard Worker break;
1593*8975f5c5SAndroid Build Coastguard Worker
1594*8975f5c5SAndroid Build Coastguard Worker default: // Float type
1595*8975f5c5SAndroid Build Coastguard Worker samplerResultType = "vec4";
1596*8975f5c5SAndroid Build Coastguard Worker break;
1597*8975f5c5SAndroid Build Coastguard Worker }
1598*8975f5c5SAndroid Build Coastguard Worker
1599*8975f5c5SAndroid Build Coastguard Worker std::string extensionRequirements;
1600*8975f5c5SAndroid Build Coastguard Worker switch (sourceTextureType)
1601*8975f5c5SAndroid Build Coastguard Worker {
1602*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::External:
1603*8975f5c5SAndroid Build Coastguard Worker extensionRequirements = "#extension GL_OES_EGL_image_external : require";
1604*8975f5c5SAndroid Build Coastguard Worker break;
1605*8975f5c5SAndroid Build Coastguard Worker
1606*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::Rectangle:
1607*8975f5c5SAndroid Build Coastguard Worker if (mFunctions->hasGLExtension("GL_ARB_texture_rectangle"))
1608*8975f5c5SAndroid Build Coastguard Worker {
1609*8975f5c5SAndroid Build Coastguard Worker extensionRequirements = "#extension GL_ARB_texture_rectangle : require";
1610*8975f5c5SAndroid Build Coastguard Worker }
1611*8975f5c5SAndroid Build Coastguard Worker else
1612*8975f5c5SAndroid Build Coastguard Worker {
1613*8975f5c5SAndroid Build Coastguard Worker ASSERT(mFunctions->isAtLeastGL(gl::Version(3, 1)));
1614*8975f5c5SAndroid Build Coastguard Worker }
1615*8975f5c5SAndroid Build Coastguard Worker break;
1616*8975f5c5SAndroid Build Coastguard Worker
1617*8975f5c5SAndroid Build Coastguard Worker default:
1618*8975f5c5SAndroid Build Coastguard Worker break;
1619*8975f5c5SAndroid Build Coastguard Worker }
1620*8975f5c5SAndroid Build Coastguard Worker
1621*8975f5c5SAndroid Build Coastguard Worker // Output variables depend on the output type
1622*8975f5c5SAndroid Build Coastguard Worker std::string outputType;
1623*8975f5c5SAndroid Build Coastguard Worker std::string outputVariableName;
1624*8975f5c5SAndroid Build Coastguard Worker std::string outputMultiplier;
1625*8975f5c5SAndroid Build Coastguard Worker switch (destComponentType)
1626*8975f5c5SAndroid Build Coastguard Worker {
1627*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
1628*8975f5c5SAndroid Build Coastguard Worker outputType = "uvec4";
1629*8975f5c5SAndroid Build Coastguard Worker outputVariableName = "outputUint";
1630*8975f5c5SAndroid Build Coastguard Worker outputMultiplier = "255.0";
1631*8975f5c5SAndroid Build Coastguard Worker break;
1632*8975f5c5SAndroid Build Coastguard Worker
1633*8975f5c5SAndroid Build Coastguard Worker default: // float type
1634*8975f5c5SAndroid Build Coastguard Worker if (version == "100")
1635*8975f5c5SAndroid Build Coastguard Worker {
1636*8975f5c5SAndroid Build Coastguard Worker outputType = "";
1637*8975f5c5SAndroid Build Coastguard Worker outputVariableName = "gl_FragColor";
1638*8975f5c5SAndroid Build Coastguard Worker outputMultiplier = "1.0";
1639*8975f5c5SAndroid Build Coastguard Worker }
1640*8975f5c5SAndroid Build Coastguard Worker else
1641*8975f5c5SAndroid Build Coastguard Worker {
1642*8975f5c5SAndroid Build Coastguard Worker outputType = "vec4";
1643*8975f5c5SAndroid Build Coastguard Worker outputVariableName = "outputFloat";
1644*8975f5c5SAndroid Build Coastguard Worker outputMultiplier = "1.0";
1645*8975f5c5SAndroid Build Coastguard Worker }
1646*8975f5c5SAndroid Build Coastguard Worker break;
1647*8975f5c5SAndroid Build Coastguard Worker }
1648*8975f5c5SAndroid Build Coastguard Worker
1649*8975f5c5SAndroid Build Coastguard Worker // Compile the fragment shader
1650*8975f5c5SAndroid Build Coastguard Worker std::ostringstream fsSourceStream;
1651*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "#version " << version << "\n";
1652*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << extensionRequirements << "\n";
1653*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "precision highp float;\n";
1654*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "uniform " << samplerType << " u_source_texture;\n";
1655*8975f5c5SAndroid Build Coastguard Worker
1656*8975f5c5SAndroid Build Coastguard Worker // Write the rest of the uniforms and varyings
1657*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "uniform bool u_multiply_alpha;\n";
1658*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "uniform bool u_unmultiply_alpha;\n";
1659*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "uniform bool u_transform_linear_to_srgb;\n";
1660*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << fsInputVariableQualifier << " vec2 v_texcoord;\n";
1661*8975f5c5SAndroid Build Coastguard Worker if (!outputType.empty())
1662*8975f5c5SAndroid Build Coastguard Worker {
1663*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << fsOutputVariableQualifier << " " << outputType << " "
1664*8975f5c5SAndroid Build Coastguard Worker << outputVariableName << ";\n";
1665*8975f5c5SAndroid Build Coastguard Worker }
1666*8975f5c5SAndroid Build Coastguard Worker
1667*8975f5c5SAndroid Build Coastguard Worker // Write the linear to sRGB function.
1668*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "\n";
1669*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "float transformLinearToSrgb(float cl)\n";
1670*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "{\n";
1671*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " if (cl <= 0.0)\n";
1672*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " return 0.0;\n";
1673*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " if (cl < 0.0031308)\n";
1674*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " return 12.92 * cl;\n";
1675*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " if (cl < 1.0)\n";
1676*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " return 1.055 * pow(cl, 0.41666) - 0.055;\n";
1677*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " return 1.0;\n";
1678*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "}\n";
1679*8975f5c5SAndroid Build Coastguard Worker
1680*8975f5c5SAndroid Build Coastguard Worker // Write the main body
1681*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "\n";
1682*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "void main()\n";
1683*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "{\n";
1684*8975f5c5SAndroid Build Coastguard Worker
1685*8975f5c5SAndroid Build Coastguard Worker std::string maxTexcoord;
1686*8975f5c5SAndroid Build Coastguard Worker switch (sourceTextureType)
1687*8975f5c5SAndroid Build Coastguard Worker {
1688*8975f5c5SAndroid Build Coastguard Worker case gl::TextureType::Rectangle:
1689*8975f5c5SAndroid Build Coastguard Worker // Valid texcoords are within source texture size
1690*8975f5c5SAndroid Build Coastguard Worker maxTexcoord = "vec2(textureSize(u_source_texture))";
1691*8975f5c5SAndroid Build Coastguard Worker break;
1692*8975f5c5SAndroid Build Coastguard Worker
1693*8975f5c5SAndroid Build Coastguard Worker default:
1694*8975f5c5SAndroid Build Coastguard Worker // Valid texcoords are in [0, 1]
1695*8975f5c5SAndroid Build Coastguard Worker maxTexcoord = "vec2(1.0)";
1696*8975f5c5SAndroid Build Coastguard Worker break;
1697*8975f5c5SAndroid Build Coastguard Worker }
1698*8975f5c5SAndroid Build Coastguard Worker
1699*8975f5c5SAndroid Build Coastguard Worker // discard if the texcoord is invalid so the blitframebuffer workaround doesn't
1700*8975f5c5SAndroid Build Coastguard Worker // write when the point sampled is outside of the source framebuffer.
1701*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " if (clamp(v_texcoord, vec2(0.0), " << maxTexcoord
1702*8975f5c5SAndroid Build Coastguard Worker << ") != v_texcoord)\n";
1703*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " {\n";
1704*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " discard;\n";
1705*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " }\n";
1706*8975f5c5SAndroid Build Coastguard Worker
1707*8975f5c5SAndroid Build Coastguard Worker // Sampling code depends on the input data type
1708*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " " << samplerResultType << " color = " << sampleFunction
1709*8975f5c5SAndroid Build Coastguard Worker << "(u_source_texture, v_texcoord);\n";
1710*8975f5c5SAndroid Build Coastguard Worker
1711*8975f5c5SAndroid Build Coastguard Worker // Perform transformation from linear to sRGB encoding.
1712*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " if (u_transform_linear_to_srgb)\n";
1713*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " {\n";
1714*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " color.x = transformLinearToSrgb(color.x);\n";
1715*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " color.y = transformLinearToSrgb(color.y);\n";
1716*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " color.z = transformLinearToSrgb(color.z);\n";
1717*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " }\n";
1718*8975f5c5SAndroid Build Coastguard Worker
1719*8975f5c5SAndroid Build Coastguard Worker // Perform unmultiply-alpha if requested.
1720*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " if (u_unmultiply_alpha && color.a != 0.0)\n";
1721*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " {\n";
1722*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " color.xyz = color.xyz / color.a;\n";
1723*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " }\n";
1724*8975f5c5SAndroid Build Coastguard Worker
1725*8975f5c5SAndroid Build Coastguard Worker // Perform premultiply-alpha if requested.
1726*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " if (u_multiply_alpha)\n";
1727*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " {\n";
1728*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " color.xyz = color.xyz * color.a;\n";
1729*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " }\n";
1730*8975f5c5SAndroid Build Coastguard Worker
1731*8975f5c5SAndroid Build Coastguard Worker // Write the conversion to the destionation type
1732*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " color = color * " << outputMultiplier << ";\n";
1733*8975f5c5SAndroid Build Coastguard Worker
1734*8975f5c5SAndroid Build Coastguard Worker // Write the output assignment code
1735*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << " " << outputVariableName << " = " << outputType << "(color);\n";
1736*8975f5c5SAndroid Build Coastguard Worker fsSourceStream << "}\n";
1737*8975f5c5SAndroid Build Coastguard Worker
1738*8975f5c5SAndroid Build Coastguard Worker std::string fsSourceStr = fsSourceStream.str();
1739*8975f5c5SAndroid Build Coastguard Worker const char *fsSourceCStr = fsSourceStr.c_str();
1740*8975f5c5SAndroid Build Coastguard Worker
1741*8975f5c5SAndroid Build Coastguard Worker GLuint fs = ANGLE_GL_TRY(context, mFunctions->createShader(GL_FRAGMENT_SHADER));
1742*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->shaderSource(fs, 1, &fsSourceCStr, nullptr));
1743*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->compileShader(fs));
1744*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CheckCompileStatus(context, mFunctions, fs));
1745*8975f5c5SAndroid Build Coastguard Worker
1746*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->attachShader(result.program, fs));
1747*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->deleteShader(fs));
1748*8975f5c5SAndroid Build Coastguard Worker }
1749*8975f5c5SAndroid Build Coastguard Worker
1750*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->bindAttribLocation(
1751*8975f5c5SAndroid Build Coastguard Worker result.program, mTexcoordAttribLocation, texcoordAttribName));
1752*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->linkProgram(result.program));
1753*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(CheckLinkStatus(context, mFunctions, result.program));
1754*8975f5c5SAndroid Build Coastguard Worker
1755*8975f5c5SAndroid Build Coastguard Worker result.sourceTextureLocation = ANGLE_GL_TRY(
1756*8975f5c5SAndroid Build Coastguard Worker context, mFunctions->getUniformLocation(result.program, "u_source_texture"));
1757*8975f5c5SAndroid Build Coastguard Worker result.scaleLocation =
1758*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->getUniformLocation(result.program, "u_scale"));
1759*8975f5c5SAndroid Build Coastguard Worker result.offsetLocation =
1760*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_TRY(context, mFunctions->getUniformLocation(result.program, "u_offset"));
1761*8975f5c5SAndroid Build Coastguard Worker result.multiplyAlphaLocation = ANGLE_GL_TRY(
1762*8975f5c5SAndroid Build Coastguard Worker context, mFunctions->getUniformLocation(result.program, "u_multiply_alpha"));
1763*8975f5c5SAndroid Build Coastguard Worker result.unMultiplyAlphaLocation = ANGLE_GL_TRY(
1764*8975f5c5SAndroid Build Coastguard Worker context, mFunctions->getUniformLocation(result.program, "u_unmultiply_alpha"));
1765*8975f5c5SAndroid Build Coastguard Worker result.transformLinearToSrgbLocation = ANGLE_GL_TRY(
1766*8975f5c5SAndroid Build Coastguard Worker context, mFunctions->getUniformLocation(result.program, "u_transform_linear_to_srgb"));
1767*8975f5c5SAndroid Build Coastguard Worker }
1768*8975f5c5SAndroid Build Coastguard Worker
1769*8975f5c5SAndroid Build Coastguard Worker *program = &result;
1770*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1771*8975f5c5SAndroid Build Coastguard Worker }
1772*8975f5c5SAndroid Build Coastguard Worker
1773*8975f5c5SAndroid Build Coastguard Worker } // namespace rx
1774