OSDN Git Service

Merge "Fix GL texture binding for TextureViews" into mnc-dev
[android-x86/frameworks-base.git] / libs / hwui / renderstate / RenderState.cpp
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "renderstate/RenderState.h"
17
18 #include "renderthread/CanvasContext.h"
19 #include "renderthread/EglManager.h"
20 #include "utils/GLUtils.h"
21
22 namespace android {
23 namespace uirenderer {
24
25 RenderState::RenderState(renderthread::RenderThread& thread)
26         : mRenderThread(thread)
27         , mViewportWidth(0)
28         , mViewportHeight(0)
29         , mFramebuffer(0) {
30     mThreadId = pthread_self();
31 }
32
33 RenderState::~RenderState() {
34     LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
35             "State object lifecycle not managed correctly");
36 }
37
38 void RenderState::onGLContextCreated() {
39     LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
40             "State object lifecycle not managed correctly");
41     mBlend = new Blend();
42     mMeshState = new MeshState();
43     mScissor = new Scissor();
44     mStencil = new Stencil();
45
46     // This is delayed because the first access of Caches makes GL calls
47     if (!mCaches) {
48         mCaches = &Caches::createInstance(*this);
49     }
50     mCaches->init();
51     mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
52 }
53
54 static void layerLostGlContext(Layer* layer) {
55     layer->onGlContextLost();
56 }
57
58 void RenderState::onGLContextDestroyed() {
59 /*
60     size_t size = mActiveLayers.size();
61     if (CC_UNLIKELY(size != 0)) {
62         ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d",
63                 mRegisteredContexts.size(), size, mActiveLayers.empty());
64         mCaches->dumpMemoryUsage();
65         for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
66                 cit != mRegisteredContexts.end(); cit++) {
67             renderthread::CanvasContext* context = *cit;
68             ALOGE("Context: %p (root = %p)", context, context->mRootRenderNode.get());
69             ALOGE("  Prefeteched layers: %zu", context->mPrefetechedLayers.size());
70             for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin();
71                     pit != context->mPrefetechedLayers.end(); pit++) {
72                 (*pit)->debugDumpLayers("    ");
73             }
74             context->mRootRenderNode->debugDumpLayers("  ");
75         }
76
77
78         if (mActiveLayers.begin() == mActiveLayers.end()) {
79             ALOGE("set has become empty. wat.");
80         }
81         for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
82              lit != mActiveLayers.end(); lit++) {
83             const Layer* layer = *(lit);
84             ALOGE("Layer %p, state %d, texlayer %d, fbo %d, buildlayered %d",
85                     layer, layer->state, layer->isTextureLayer(), layer->getFbo(), layer->wasBuildLayered);
86         }
87         LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
88     }
89 */
90
91     // TODO: reset all cached state in state objects
92     std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
93     mAssetAtlas.terminate();
94
95     mCaches->terminate();
96
97     delete mBlend;
98     mBlend = nullptr;
99     delete mMeshState;
100     mMeshState = nullptr;
101     delete mScissor;
102     mScissor = nullptr;
103     delete mStencil;
104     mStencil = nullptr;
105 }
106
107 void RenderState::setViewport(GLsizei width, GLsizei height) {
108     mViewportWidth = width;
109     mViewportHeight = height;
110     glViewport(0, 0, mViewportWidth, mViewportHeight);
111 }
112
113
114 void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) {
115     *outWidth = mViewportWidth;
116     *outHeight = mViewportHeight;
117 }
118
119 void RenderState::bindFramebuffer(GLuint fbo) {
120     if (mFramebuffer != fbo) {
121         mFramebuffer = fbo;
122         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
123     }
124 }
125
126 void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
127     interruptForFunctorInvoke();
128     (*functor)(mode, info);
129     resumeFromFunctorInvoke();
130 }
131
132 void RenderState::interruptForFunctorInvoke() {
133     mCaches->setProgram(nullptr);
134     mCaches->textureState().resetActiveTexture();
135     meshState().unbindMeshBuffer();
136     meshState().unbindIndicesBuffer();
137     meshState().resetVertexPointers();
138     meshState().disableTexCoordsVertexArray();
139     debugOverdraw(false, false);
140 }
141
142 void RenderState::resumeFromFunctorInvoke() {
143     glViewport(0, 0, mViewportWidth, mViewportHeight);
144     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
145     debugOverdraw(false, false);
146
147     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
148
149     scissor().invalidate();
150     blend().invalidate();
151
152     mCaches->textureState().activateTexture(0);
153     mCaches->textureState().resetBoundTextures();
154 }
155
156 void RenderState::debugOverdraw(bool enable, bool clear) {
157     if (Properties::debugOverdraw && mFramebuffer == 0) {
158         if (clear) {
159             scissor().setEnabled(false);
160             stencil().clear();
161         }
162         if (enable) {
163             stencil().enableDebugWrite();
164         } else {
165             stencil().disable();
166         }
167     }
168 }
169
170 void RenderState::requireGLContext() {
171     assertOnGLThread();
172     LOG_ALWAYS_FATAL_IF(!mRenderThread.eglManager().hasEglContext(),
173             "No GL context!");
174 }
175
176 void RenderState::assertOnGLThread() {
177     pthread_t curr = pthread_self();
178     LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!");
179 }
180
181 class DecStrongTask : public renderthread::RenderTask {
182 public:
183     DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}
184
185     virtual void run() override {
186         mObject->decStrong(nullptr);
187         mObject = nullptr;
188         delete this;
189     }
190
191 private:
192     VirtualLightRefBase* mObject;
193 };
194
195 void RenderState::postDecStrong(VirtualLightRefBase* object) {
196     mRenderThread.queue(new DecStrongTask(object));
197 }
198
199 ///////////////////////////////////////////////////////////////////////////////
200 // Render
201 ///////////////////////////////////////////////////////////////////////////////
202
203 void RenderState::render(const Glop& glop) {
204     const Glop::Mesh& mesh = glop.mesh;
205     const Glop::Mesh::Vertices& vertices = mesh.vertices;
206     const Glop::Mesh::Indices& indices = mesh.indices;
207     const Glop::Fill& fill = glop.fill;
208
209     // ---------------------------------------------
210     // ---------- Program + uniform setup ----------
211     // ---------------------------------------------
212     mCaches->setProgram(fill.program);
213
214     if (fill.colorEnabled) {
215         fill.program->setColor(fill.color);
216     }
217
218     fill.program->set(glop.transform.ortho,
219             glop.transform.modelView,
220             glop.transform.canvas,
221             glop.transform.fudgingOffset);
222
223     // Color filter uniforms
224     if (fill.filterMode == ProgramDescription::kColorBlend) {
225         const FloatColor& color = fill.filter.color;
226         glUniform4f(mCaches->program().getUniform("colorBlend"),
227                 color.r, color.g, color.b, color.a);
228     } else if (fill.filterMode == ProgramDescription::kColorMatrix) {
229         glUniformMatrix4fv(mCaches->program().getUniform("colorMatrix"), 1, GL_FALSE,
230                 fill.filter.matrix.matrix);
231         glUniform4fv(mCaches->program().getUniform("colorMatrixVector"), 1,
232                 fill.filter.matrix.vector);
233     }
234
235     // Round rect clipping uniforms
236     if (glop.roundRectClipState) {
237         // TODO: avoid query, and cache values (or RRCS ptr) in program
238         const RoundRectClipState* state = glop.roundRectClipState;
239         const Rect& innerRect = state->innerRect;
240         glUniform4f(fill.program->getUniform("roundRectInnerRectLTRB"),
241                 innerRect.left, innerRect.top,
242                 innerRect.right, innerRect.bottom);
243         glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"),
244                 1, GL_FALSE, &state->matrix.data[0]);
245
246         // add half pixel to round out integer rect space to cover pixel centers
247         float roundedOutRadius = state->radius + 0.5f;
248         glUniform1f(fill.program->getUniform("roundRectRadius"),
249                 roundedOutRadius);
250     }
251
252     // --------------------------------
253     // ---------- Mesh setup ----------
254     // --------------------------------
255     // vertices
256     const bool force = meshState().bindMeshBufferInternal(vertices.bufferObject)
257             || (vertices.position != nullptr);
258     meshState().bindPositionVertexPointer(force, vertices.position, vertices.stride);
259
260     // indices
261     meshState().bindIndicesBufferInternal(indices.bufferObject);
262
263     if (vertices.attribFlags & VertexAttribFlags::kTextureCoord) {
264         const Glop::Fill::TextureData& texture = fill.texture;
265         // texture always takes slot 0, shader samplers increment from there
266         mCaches->textureState().activateTexture(0);
267
268         if (texture.clamp != GL_INVALID_ENUM) {
269             texture.texture->setWrap(texture.clamp, true, false, texture.target);
270         }
271         if (texture.filter != GL_INVALID_ENUM) {
272             texture.texture->setFilter(texture.filter, true, false, texture.target);
273         }
274
275         mCaches->textureState().bindTexture(texture.target, texture.texture->id);
276         meshState().enableTexCoordsVertexArray();
277         meshState().bindTexCoordsVertexPointer(force, vertices.texCoord, vertices.stride);
278
279         if (texture.textureTransform) {
280             glUniformMatrix4fv(fill.program->getUniform("mainTextureTransform"), 1,
281                     GL_FALSE, &texture.textureTransform->data[0]);
282         }
283     } else {
284         meshState().disableTexCoordsVertexArray();
285     }
286     int colorLocation = -1;
287     if (vertices.attribFlags & VertexAttribFlags::kColor) {
288         colorLocation = fill.program->getAttrib("colors");
289         glEnableVertexAttribArray(colorLocation);
290         glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, vertices.stride, vertices.color);
291     }
292     int alphaLocation = -1;
293     if (vertices.attribFlags & VertexAttribFlags::kAlpha) {
294         // NOTE: alpha vertex position is computed assuming no VBO
295         const void* alphaCoords = ((const GLbyte*) vertices.position) + kVertexAlphaOffset;
296         alphaLocation = fill.program->getAttrib("vtxAlpha");
297         glEnableVertexAttribArray(alphaLocation);
298         glVertexAttribPointer(alphaLocation, 1, GL_FLOAT, GL_FALSE, vertices.stride, alphaCoords);
299     }
300     // Shader uniforms
301     SkiaShader::apply(*mCaches, fill.skiaShaderData);
302
303     // ------------------------------------
304     // ---------- GL state setup ----------
305     // ------------------------------------
306     blend().setFactors(glop.blend.src, glop.blend.dst);
307
308     // ------------------------------------
309     // ---------- Actual drawing ----------
310     // ------------------------------------
311     if (indices.bufferObject == meshState().getQuadListIBO()) {
312         // Since the indexed quad list is of limited length, we loop over
313         // the glDrawXXX method while updating the vertex pointer
314         GLsizei elementsCount = mesh.elementCount;
315         const GLbyte* vertexData = static_cast<const GLbyte*>(vertices.position);
316         while (elementsCount > 0) {
317             GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
318
319             // rebind pointers without forcing, since initial bind handled above
320             meshState().bindPositionVertexPointer(false, vertexData, vertices.stride);
321             if (vertices.attribFlags & VertexAttribFlags::kTextureCoord) {
322                 meshState().bindTexCoordsVertexPointer(false,
323                         vertexData + kMeshTextureOffset, vertices.stride);
324             }
325
326             glDrawElements(mesh.primitiveMode, drawCount, GL_UNSIGNED_SHORT, nullptr);
327             elementsCount -= drawCount;
328             vertexData += (drawCount / 6) * 4 * vertices.stride;
329         }
330     } else if (indices.bufferObject || indices.indices) {
331         glDrawElements(mesh.primitiveMode, mesh.elementCount, GL_UNSIGNED_SHORT, indices.indices);
332     } else {
333         glDrawArrays(mesh.primitiveMode, 0, mesh.elementCount);
334     }
335
336     // -----------------------------------
337     // ---------- Mesh teardown ----------
338     // -----------------------------------
339     if (vertices.attribFlags & VertexAttribFlags::kAlpha) {
340         glDisableVertexAttribArray(alphaLocation);
341     }
342     if (vertices.attribFlags & VertexAttribFlags::kColor) {
343         glDisableVertexAttribArray(colorLocation);
344     }
345 }
346
347 void RenderState::dump() {
348     blend().dump();
349     meshState().dump();
350     scissor().dump();
351     stencil().dump();
352 }
353
354 } /* namespace uirenderer */
355 } /* namespace android */