//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] TextureBufferDsa::TextureBufferDsa(OpenGLRenderer &openGLRenderer, uint32_t numberOfBytes, Renderer::TextureFormat::Enum textureFormat, const void *data, Renderer::BufferUsage bufferUsage) : TextureBuffer(openGLRenderer) { if (openGLRenderer.getExtensions().isGL_ARB_direct_state_access()) { { // Buffer part // Create the OpenGL texture buffer glCreateBuffers(1, &mOpenGLTextureBuffer); // Upload the data // -> Usage: These constants directly map to "GL_ARB_vertex_buffer_object" and OpenGL ES 2 constants, do not change them glNamedBufferData(mOpenGLTextureBuffer, static_cast<GLsizeiptr>(numberOfBytes), data, static_cast<GLenum>(bufferUsage)); } { // Texture part // Create the OpenGL texture instance glCreateTextures(GL_TEXTURE_BUFFER_ARB, 1, &mOpenGLTexture); // Attach the storage for the buffer object to the buffer texture glTextureBuffer(mOpenGLTexture, Mapping::getOpenGLInternalFormat(textureFormat), mOpenGLTextureBuffer); } } else { // Create the OpenGL texture buffer glGenBuffersARB(1, &mOpenGLTextureBuffer); // Create the OpenGL texture instance glGenTextures(1, &mOpenGLTexture); // Buffer part // -> Upload the data // -> Usage: These constants directly map to "GL_ARB_vertex_buffer_object" and OpenGL ES 2 constants, do not change them glNamedBufferDataEXT(mOpenGLTextureBuffer, static_cast<GLsizeiptr>(numberOfBytes), data, static_cast<GLenum>(bufferUsage)); { // Texture part #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Backup the currently bound OpenGL texture GLint openGLTextureBackup = 0; glGetIntegerv(GL_TEXTURE_BINDING_BUFFER_ARB, &openGLTextureBackup); #endif // Make this OpenGL texture instance to the currently used one glBindTexture(GL_TEXTURE_BUFFER_ARB, mOpenGLTexture); // Attaches the storage for the buffer object to the active buffer texture // -> Sadly, there's no direct state access (DSA) function defined for this in "GL_EXT_direct_state_access" glTexBufferARB(GL_TEXTURE_BUFFER_ARB, Mapping::getOpenGLInternalFormat(textureFormat), mOpenGLTextureBuffer); #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Be polite and restore the previous bound OpenGL texture glBindTexture(GL_TEXTURE_BUFFER_ARB, static_cast<GLuint>(openGLTextureBackup)); #endif } } }
void Layer::updateLightPosFromRenderer(const OpenGLRenderer& rootRenderer) { if (renderer && rendererLightPosDirty) { // re-init renderer's light position, based upon last cached location in window Vector3 lightPos = rootRenderer.getLightCenter(); cachedInvTransformInWindow.mapPoint3d(lightPos); renderer->initLight(rootRenderer.getLightRadius(), rootRenderer.getAmbientShadowAlpha(), rootRenderer.getSpotShadowAlpha()); renderer->setLightCenter(lightPos); rendererLightPosDirty = false; } }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] VertexArrayNoVao::VertexArrayNoVao(OpenGLRenderer &openGLRenderer, const Renderer::VertexAttributes& vertexAttributes, uint32_t numberOfVertexBuffers, const Renderer::VertexArrayVertexBuffer *vertexBuffers, IndexBuffer *indexBuffer) : VertexArray(openGLRenderer, indexBuffer, InternalResourceType::NO_VAO), mNumberOfAttributes(vertexAttributes.numberOfAttributes), mAttributes(mNumberOfAttributes ? new Renderer::VertexAttribute[mNumberOfAttributes] : nullptr), mNumberOfVertexBuffers(numberOfVertexBuffers), mVertexBuffers(numberOfVertexBuffers ? new Renderer::VertexArrayVertexBuffer[numberOfVertexBuffers] : nullptr), mIsGL_ARB_instanced_arrays(openGLRenderer.getExtensions().isGL_ARB_instanced_arrays()) { // Copy over the data if (nullptr != mAttributes) { memcpy(mAttributes, vertexAttributes.attributes, sizeof(Renderer::VertexAttribute) * mNumberOfAttributes); } if (nullptr != mVertexBuffers) { memcpy(mVertexBuffers, vertexBuffers, sizeof(Renderer::VertexArrayVertexBuffer) * mNumberOfVertexBuffers); } // Add a reference to the used vertex buffers const Renderer::VertexArrayVertexBuffer *vertexBufferEnd = mVertexBuffers + mNumberOfVertexBuffers; for (const Renderer::VertexArrayVertexBuffer *vertexBuffer = mVertexBuffers; vertexBuffer < vertexBufferEnd; ++vertexBuffer) { vertexBuffer->vertexBuffer->addReference(); } }
void MainWidgetPrivate::paintGL() { OpenGLProfiler::BeginFrame(); if (m_sceneManager.activeScene()) { m_renderer.render(*m_sceneManager.currentScene()); } OpenGLProfiler::EndFrame(); }
void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) { if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging ALOGW("Error: %s is drawing after destruction, size %d", getName(), mSize); CRASH(); } if (mSize == 0 || mAlpha <= 0) { DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string()); return; } #if DEBUG_DISPLAY_LIST Rect* clipRect = renderer.getClipRect(); DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.0f, %.0f, %.0f", level * 2, "", this, mName.string(), clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); #endif int restoreTo = renderer.getSaveCount(); handler(mSaveOp->reinit(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag), PROPERTY_SAVECOUNT, mClipToBounds); DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); setViewProperties<T>(renderer, handler, level + 1); if (mClipToBounds && renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); renderer.restoreToCount(restoreTo); renderer.setOverrideLayerAlpha(1.0f); return; } DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); int saveCount = renderer.getSaveCount() - 1; for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { DisplayListOp *op = mDisplayListData->displayListOps[i]; #if DEBUG_DISPLAY_LIST op->output(level + 1); #endif logBuffer.writeCommand(level, op->name()); handler(op, saveCount, mClipToBounds); } DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds); renderer.restoreToCount(restoreTo); renderer.setOverrideLayerAlpha(1.0f); }
void MainWidgetPrivate::initializeGL() { // Global Setup (Rarely Changed) GL::glEnable(GL_CULL_FACE); GL::glEnable(GL_DEPTH_TEST); GL::glClearDepthf(1.0f); GL::glDepthFunc(GL_LEQUAL); // Create Renderer m_renderer.create(); m_renderer.bind(); m_renderer.addPass<GBufferPass>(); // => Nothing (Constructs Globals) m_renderer.addPass<ScreenSpaceAmbientOcclusion>(); // => SSAO Buffer m_renderer.addPass<PreparePresentationPass>(); // => RenderBuffer m_renderer.addPass<EnvironmentPass>(); // => Ambient Term m_renderer.addPass<LightAccumulationPass>(); // => Non-Shadowed Lights m_renderer.addPass<ShadowedLightAccumulationPass>(); // => RenderBuffer m_renderer.addPass<MotionBlurPass>(); // => RenderBuffer m_renderer.addPass<ViewportPresentationPass>(); // => Nothing (Displays RenderBuffer) m_initialized = true; }
void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler, const int level) { #if DEBUG_DISPLAY_LIST if (g_HWUI_debug_display_list) { outputViewProperties(level); } #endif updateMatrix(); if (mLeft != 0 || mTop != 0) { renderer.translate(mLeft, mTop); } if (mStaticMatrix) { renderer.concatMatrix(mStaticMatrix); } else if (mAnimationMatrix) { renderer.concatMatrix(mAnimationMatrix); } if (mMatrixFlags != 0) { if (mMatrixFlags == TRANSLATION) { renderer.translate(mTranslationX, mTranslationY); } else { renderer.concatMatrix(mTransformMatrix); } } /// M: [ALPS01255047] rollback google changelist /// don't disable the clip in case texture layer has transform bool clipToBoundsNeeded = mClipToBounds; if (mAlpha < 1) { if (mCaching) { renderer.setOverrideLayerAlpha(mAlpha); clipToBoundsNeeded = false; // clipping done by layer } else if (!mHasOverlappingRendering) { renderer.scaleAlpha(mAlpha); } else { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag; if (clipToBoundsNeeded) { saveFlags |= SkCanvas::kClipToLayer_SaveFlag; clipToBoundsNeeded = false; // clipping done by saveLayer } handler(mSaveLayerOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT, mClipToBounds); } } if (clipToBoundsNeeded) { handler(mClipRectOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, SkRegion::kIntersect_Op), PROPERTY_SAVECOUNT, mClipToBounds); } }
void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) { DISPLAY_LIST_LOGD("%*s%d projected children:", (handler.level() + 1) * 2, "", mProjectedNodes.size()); const SkPath* projectionReceiverOutline = properties().getOutline().getPath(); int restoreTo = renderer.getSaveCount(); LinearAllocator& alloc = handler.allocator(); handler(new (alloc) SaveOp(SaveFlags::MatrixClip), PROPERTY_SAVECOUNT, properties().getClipToBounds()); // Transform renderer to match background we're projecting onto // (by offsetting canvas by translationX/Y of background rendernode, since only those are set) const DisplayListOp* op = #if HWUI_NEW_OPS nullptr; LOG_ALWAYS_FATAL("unsupported"); #else (mDisplayList->getOps()[mDisplayList->projectionReceiveIndex]); #endif const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op); const RenderProperties& backgroundProps = backgroundOp->renderNode->properties(); renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY()); // If the projection receiver has an outline, we mask projected content to it // (which we know, apriori, are all tessellated paths) renderer.setProjectionPathMask(alloc, projectionReceiverOutline); // draw projected nodes for (size_t i = 0; i < mProjectedNodes.size(); i++) { renderNodeOp_t* childOp = mProjectedNodes[i]; // matrix save, concat, and restore can be done safely without allocating operations int restoreTo = renderer.save(SaveFlags::Matrix); renderer.concatMatrix(childOp->transformFromCompositingAncestor); childOp->skipInOrderDraw = false; // this is horrible, I'm so sorry everyone handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds()); childOp->skipInOrderDraw = true; renderer.restoreToCount(restoreTo); } handler(new (alloc) RestoreToCountOp(restoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds()); }
void MainWidgetPrivate::resizeGL(int width, int height) { m_renderer.resize(width, height); }
void MainWidgetPrivate::teardownGL() { m_renderer.teardown(); }
int main(int argc, char **argv) { if (!InitKinect()) return -1; OpenGLRenderer *renderer = new OpenGLRenderer(); IplImage* rgbImg; IplImage* depthImg; rgbImg = cvCreateImage(cvSize(640,480), IPL_DEPTH_8U, 3); depthImg = cvCreateImage(cvSize(640,480), IPL_DEPTH_8U, 3); IplImage* rgbCopy = cvCreateImage( cvSize(640,480),IPL_DEPTH_8U, 3); IplImage* depthCopy = cvCreateImage(cvSize(640,480), IPL_DEPTH_8U, 3); IplImage* rgbOut = cvCreateImage( cvSize(640,480),IPL_DEPTH_8U, 1); enum TrackingState { TRACK_HEAD, TRACKING }; TrackingState state = TRACK_HEAD; while (true) { ProcessInput(); if (!SynchronizeDrawingData()) continue; switch (state) { case TRACK_HEAD: { cvSetData(rgbImg, GetKinectRgbData(), 640*3); cvSetData(depthImg, GetKinectDepthData(), 640*3); cvCopy( rgbImg, rgbCopy, 0 ); //cvCopy( rgbImg, rgbOut, 0 ); cvCopy( depthImg, depthCopy, 0 ); if(IsKeyUp(306)) { //left ctrl state = TRACKING; printf("start tracking!\n"); } const CvRect &selection = ProcessSelection(); if ((selection.x + selection.y + selection.width + selection.height)!=0) { cvRectangle( rgbImg, cvPoint(selection.x, selection.y), cvPoint(selection.x+selection.width, selection.y+selection.height), cvScalar(255, 0, 0)); } renderer->Render((uint8_t*)rgbCopy->imageData, (uint8_t*)depthImg->imageData); } break; case TRACKING: cvSetData(rgbImg, GetKinectRgbData(), 640*3); cvSetData(depthImg, GetKinectDepthData(), 640*3); printf("compare!\n"); cvCmp( rgbImg, rgbCopy, rgbOut, CV_CMP_EQ ); printf("endcompare!\n"); fflush(stdout); //ProcessSelection(); //renderer->RenderExtra((uint8_t*)backproject->imageData, 640,480, 1); //renderer->RenderExtra((uint8_t*)mask->imageData, 640,480, 1); //renderer->RenderExtra((uint8_t*)hue->imageData, 640,480, 1); //renderer->RenderExtra((uint8_t*)rgbOut->imageData, 640,480, 1); //renderer->RenderExtra((uint8_t*)histimg->imageData, 320,200, 3); printf("1!\n"); renderer->Render((uint8_t*)rgbCopy->imageData, (uint8_t*)depthImg->imageData); break; } if (!renderer->Update()) return 1; sleep(0); } delete renderer; return 0; }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] VertexArrayVaoDsa::VertexArrayVaoDsa(OpenGLRenderer &openGLRenderer, const Renderer::VertexAttributes& vertexAttributes, uint32_t numberOfVertexBuffers, const Renderer::VertexArrayVertexBuffer *vertexBuffers, IndexBuffer *indexBuffer) : VertexArrayVao(openGLRenderer, numberOfVertexBuffers, vertexBuffers, indexBuffer) { // Vertex buffer reference handling is done within the base class "VertexArrayVao" const bool isARB_DSA = openGLRenderer.getExtensions().isGL_ARB_direct_state_access(); if (isARB_DSA) { // Create the OpenGL vertex array glCreateVertexArrays(1, &mOpenGLVertexArray); } else { // Create the OpenGL vertex array glGenVertexArrays(1, &mOpenGLVertexArray); } // Loop through all attributes // -> We're using "glBindAttribLocationARB()" when linking the program so we have known attribute locations (the vertex array can't know about the program) GLuint attributeLocation = 0; const Renderer::VertexAttribute *attributeEnd = vertexAttributes.attributes + vertexAttributes.numberOfAttributes; for (const Renderer::VertexAttribute *attribute = vertexAttributes.attributes; attribute < attributeEnd; ++attribute, ++attributeLocation) { // Set the OpenGL vertex attribute pointer // TODO(co) Add security check: Is the given resource one of the currently used renderer? const Renderer::VertexArrayVertexBuffer& vertexArrayVertexBuffer = vertexBuffers[attribute->inputSlot]; if (isARB_DSA) { // Enable attribute glEnableVertexArrayAttrib(mOpenGLVertexArray, attributeLocation); // Set up the format for my attribute glVertexArrayAttribFormat(mOpenGLVertexArray, attributeLocation, Mapping::getOpenGLSize(attribute->vertexAttributeFormat), Mapping::getOpenGLType(attribute->vertexAttributeFormat), static_cast<GLboolean>(Mapping::isOpenGLVertexAttributeFormatNormalized(attribute->vertexAttributeFormat)), static_cast<GLuint>(attribute->alignedByteOffset)); // Bind vertex buffer to buffer point glVertexArrayVertexBuffer(mOpenGLVertexArray, attributeLocation, static_cast<VertexBuffer*>(vertexArrayVertexBuffer.vertexBuffer)->getOpenGLArrayBuffer(), 0, // No offset to the first element of the buffer static_cast<GLsizei>(vertexArrayVertexBuffer.strideInBytes)); // Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays" if (attribute->instancesPerElement > 0 && openGLRenderer.getExtensions().isGL_ARB_instanced_arrays()) { glVertexArrayBindingDivisor(mOpenGLVertexArray, attributeLocation, attribute->instancesPerElement); } } else { glVertexArrayVertexAttribOffsetEXT(mOpenGLVertexArray, static_cast<VertexBuffer*>(vertexArrayVertexBuffer.vertexBuffer)->getOpenGLArrayBuffer(), attributeLocation, Mapping::getOpenGLSize(attribute->vertexAttributeFormat), Mapping::getOpenGLType(attribute->vertexAttributeFormat), static_cast<GLboolean>(Mapping::isOpenGLVertexAttributeFormatNormalized(attribute->vertexAttributeFormat)), static_cast<GLsizei>(vertexArrayVertexBuffer.strideInBytes), static_cast<GLintptr>(attribute->alignedByteOffset)); // Per-instance instead of per-vertex requires "GL_ARB_instanced_arrays" if (attribute->instancesPerElement > 0 && openGLRenderer.getExtensions().isGL_ARB_instanced_arrays()) { // Sadly, DSA has no support for "GL_ARB_instanced_arrays", so, we have to use the bind way // -> Keep the bind-horror as local as possible #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Backup the currently bound OpenGL vertex array GLint openGLVertexArrayBackup = 0; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &openGLVertexArrayBackup); #endif // Bind this OpenGL vertex array glBindVertexArray(mOpenGLVertexArray); // Set divisor glVertexAttribDivisorARB(attributeLocation, attribute->instancesPerElement); #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Be polite and restore the previous bound OpenGL vertex array glBindVertexArray(static_cast<GLuint>(openGLVertexArrayBackup)); #endif } // Enable OpenGL vertex attribute array glEnableVertexArrayAttribEXT(mOpenGLVertexArray, attributeLocation); } } // Check the used index buffer // -> In case of no index buffer we don't bind buffer 0, there's not really a point in it if (nullptr != indexBuffer) { if (isARB_DSA) { // Bind the index buffer glVertexArrayElementBuffer(mOpenGLVertexArray, indexBuffer->getOpenGLElementArrayBuffer()); } else { // Sadly, EXT DSA has no support for element array buffer, so, we have to use the bind way // -> Keep the bind-horror as local as possible #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Backup the currently bound OpenGL vertex array GLint openGLVertexArrayBackup = 0; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &openGLVertexArrayBackup); // Backup the currently bound OpenGL element array buffer GLint openGLElementArrayBufferBackup = 0; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &openGLElementArrayBufferBackup); #endif // Bind this OpenGL vertex array glBindVertexArray(mOpenGLVertexArray); // Bind OpenGL element array buffer glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexBuffer->getOpenGLElementArrayBuffer()); #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Be polite and restore the previous bound OpenGL vertex array glBindVertexArray(static_cast<GLuint>(openGLVertexArrayBackup)); // Be polite and restore the previous bound OpenGL element array buffer glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, static_cast<GLuint>(openGLElementArrayBufferBackup)); #endif } } }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] Texture2DArrayDsa::Texture2DArrayDsa(OpenGLRenderer &openGLRenderer, uint32_t width, uint32_t height, uint32_t numberOfSlices, Renderer::TextureFormat::Enum textureFormat, const void *data, uint32_t flags) : Texture2DArray(openGLRenderer, width, height, numberOfSlices) { #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Backup the currently set alignment GLint openGLAlignmentBackup = 0; glGetIntegerv(GL_UNPACK_ALIGNMENT, &openGLAlignmentBackup); #endif // Set correct alignment glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Create the OpenGL texture instance const bool isARB_DSA = openGLRenderer.getExtensions().isGL_ARB_direct_state_access(); if (isARB_DSA) { glCreateTextures(GL_TEXTURE_2D_ARRAY_EXT, 1, &mOpenGLTexture); } else { glGenTextures(1, &mOpenGLTexture); } // Upload the base map of the texture (mipmaps are automatically created as soon as the base map is changed) if (isARB_DSA) { glTextureStorage3D(mOpenGLTexture, 1, Mapping::getOpenGLInternalFormat(textureFormat), static_cast<GLsizei>(width), static_cast<GLsizei>(height), static_cast<GLsizei>(numberOfSlices)); if (nullptr != data) { glTextureSubImage3D(mOpenGLTexture, 0, 0, 0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height), static_cast<GLsizei>(numberOfSlices), Mapping::getOpenGLFormat(textureFormat), Mapping::getOpenGLType(textureFormat), data); } } else { glTextureImage3DEXT(mOpenGLTexture, GL_TEXTURE_2D_ARRAY_EXT, 0, static_cast<GLint>(Mapping::getOpenGLInternalFormat(textureFormat)), static_cast<GLsizei>(width), static_cast<GLsizei>(height), static_cast<GLsizei>(numberOfSlices), 0, Mapping::getOpenGLFormat(textureFormat), Mapping::getOpenGLType(textureFormat), data); } // Build mipmaps automatically on the GPU? (or GPU driver) if (flags & Renderer::TextureFlag::GENERATE_MIPMAPS) { if (isARB_DSA) { glGenerateTextureMipmap(mOpenGLTexture); glTextureParameteri(mOpenGLTexture, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { glGenerateTextureMipmapEXT(mOpenGLTexture, GL_TEXTURE_2D_ARRAY_EXT); glTextureParameteriEXT(mOpenGLTexture, GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } } else { if (isARB_DSA) { glTextureParameteri(mOpenGLTexture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { glTextureParameteriEXT(mOpenGLTexture, GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } } if (isARB_DSA) { glTextureParameteri(mOpenGLTexture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTextureParameteriEXT(mOpenGLTexture, GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } #ifndef OPENGLRENDERER_NO_STATE_CLEANUP // Restore previous alignment glPixelStorei(GL_UNPACK_ALIGNMENT, openGLAlignmentBackup); #endif }
void RenderNode::issueOperationsOf3dChildren(ChildrenSelectMode mode, const Matrix4& initialTransform, const std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes, OpenGLRenderer& renderer, T& handler) { const int size = zTranslatedNodes.size(); if (size == 0 || (mode == ChildrenSelectMode::NegativeZChildren && zTranslatedNodes[0].key > 0.0f) || (mode == ChildrenSelectMode::PositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) { // no 3d children to draw return; } // Apply the base transform of the parent of the 3d children. This isolates // 3d children of the current chunk from transformations made in previous chunks. int rootRestoreTo = renderer.save(SaveFlags::Matrix); renderer.setGlobalMatrix(initialTransform); /** * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters * with very similar Z heights to draw together. * * This way, if Views A & B have the same Z height and are both casting shadows, the shadows are * underneath both, and neither's shadow is drawn on top of the other. */ const size_t nonNegativeIndex = findNonNegativeIndex(zTranslatedNodes); size_t drawIndex, shadowIndex, endIndex; if (mode == ChildrenSelectMode::NegativeZChildren) { drawIndex = 0; endIndex = nonNegativeIndex; shadowIndex = endIndex; // draw no shadows } else { drawIndex = nonNegativeIndex; endIndex = size; shadowIndex = drawIndex; // potentially draw shadow for each pos Z child } DISPLAY_LIST_LOGD("%*s%d %s 3d children:", (handler.level() + 1) * 2, "", endIndex - drawIndex, mode == kNegativeZChildren ? "negative" : "positive"); float lastCasterZ = 0.0f; while (shadowIndex < endIndex || drawIndex < endIndex) { if (shadowIndex < endIndex) { DrawRenderNodeOp* casterOp = zTranslatedNodes[shadowIndex].value; RenderNode* caster = casterOp->renderNode; const float casterZ = zTranslatedNodes[shadowIndex].key; // attempt to render the shadow if the caster about to be drawn is its caster, // OR if its caster's Z value is similar to the previous potential caster if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) { caster->issueDrawShadowOperation(casterOp->localMatrix, handler); lastCasterZ = casterZ; // must do this even if current caster not casting a shadow shadowIndex++; continue; } } // only the actual child DL draw needs to be in save/restore, // since it modifies the renderer's matrix int restoreTo = renderer.save(SaveFlags::Matrix); DrawRenderNodeOp* childOp = zTranslatedNodes[drawIndex].value; renderer.concatMatrix(childOp->localMatrix); childOp->skipInOrderDraw = false; // this is horrible, I'm so sorry everyone handler(childOp, renderer.getSaveCount() - 1, properties().getClipToBounds()); childOp->skipInOrderDraw = true; renderer.restoreToCount(restoreTo); drawIndex++; } renderer.restoreToCount(rootRestoreTo); }
void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) { #if DEBUG_DISPLAY_LIST properties().debugOutputProperties(handler.level() + 1); #endif if (properties().getLeft() != 0 || properties().getTop() != 0) { renderer.translate(properties().getLeft(), properties().getTop()); } if (properties().getStaticMatrix()) { renderer.concatMatrix(*properties().getStaticMatrix()); } else if (properties().getAnimationMatrix()) { renderer.concatMatrix(*properties().getAnimationMatrix()); } if (properties().hasTransformMatrix()) { if (properties().isTransformTranslateOnly()) { renderer.translate(properties().getTranslationX(), properties().getTranslationY()); } else { renderer.concatMatrix(*properties().getTransformMatrix()); } } const bool isLayer = properties().effectiveLayerType() != LayerType::None; int clipFlags = properties().getClippingFlags(); if (properties().getAlpha() < 1) { if (isLayer) { clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer } if (CC_LIKELY(isLayer || !properties().getHasOverlappingRendering())) { // simply scale rendering content's alpha renderer.scaleAlpha(properties().getAlpha()); } else { // savelayer needed to create an offscreen buffer Rect layerBounds(0, 0, getWidth(), getHeight()); if (clipFlags) { properties().getClippingRectForFlags(clipFlags, &layerBounds); clipFlags = 0; // all clipping done by savelayer } SaveLayerOp* op = new (handler.allocator()) SaveLayerOp( layerBounds.left, layerBounds.top, layerBounds.right, layerBounds.bottom, (int) (properties().getAlpha() * 255), SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer); handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds()); } if (CC_UNLIKELY(ATRACE_ENABLED() && properties().promotedToLayer())) { // pretend alpha always causes savelayer to warn about // performance problem affecting old versions ATRACE_FORMAT("%s alpha caused saveLayer %dx%d", getName(), static_cast<int>(getWidth()), static_cast<int>(getHeight())); } } if (clipFlags) { Rect clipRect; properties().getClippingRectForFlags(clipFlags, &clipRect); ClipRectOp* op = new (handler.allocator()) ClipRectOp( clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, SkRegion::kIntersect_Op); handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds()); } // TODO: support nesting round rect clips if (mProperties.getRevealClip().willClip()) { Rect bounds; mProperties.getRevealClip().getBounds(&bounds); renderer.setClippingRoundRect(handler.allocator(), bounds, mProperties.getRevealClip().getRadius()); } else if (mProperties.getOutline().willClip()) { renderer.setClippingOutline(handler.allocator(), &(mProperties.getOutline())); } }
void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { if (mDisplayList->isEmpty()) { DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", handler.level() * 2, "", this, getName()); return; } #if HWUI_NEW_OPS const bool drawLayer = false; #else const bool drawLayer = (mLayer && (&renderer != mLayer->renderer.get())); #endif // If we are updating the contents of mLayer, we don't want to apply any of // the RenderNode's properties to this issueOperations pass. Those will all // be applied when the layer is drawn, aka when this is true. const bool useViewProperties = (!mLayer || drawLayer); if (useViewProperties) { const Outline& outline = properties().getOutline(); if (properties().getAlpha() <= 0 || (outline.getShouldClip() && outline.isEmpty()) || properties().getScaleX() == 0 || properties().getScaleY() == 0) { DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", handler.level() * 2, "", this, getName()); return; } } handler.startMark(getName()); #if DEBUG_DISPLAY_LIST const Rect& clipRect = renderer.getLocalClipBounds(); DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), localClipBounds: %.0f, %.0f, %.0f, %.0f", handler.level() * 2, "", this, getName(), clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); #endif LinearAllocator& alloc = handler.allocator(); int restoreTo = renderer.getSaveCount(); handler(new (alloc) SaveOp(SaveFlags::MatrixClip), PROPERTY_SAVECOUNT, properties().getClipToBounds()); DISPLAY_LIST_LOGD("%*sSave %d %d", (handler.level() + 1) * 2, "", SaveFlags::MatrixClip, restoreTo); if (useViewProperties) { setViewProperties<T>(renderer, handler); } #if HWUI_NEW_OPS LOG_ALWAYS_FATAL("legacy op traversal not supported"); #else bool quickRejected = properties().getClipToBounds() && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight()); if (!quickRejected) { Matrix4 initialTransform(*(renderer.currentTransform())); renderer.setBaseTransform(initialTransform); if (drawLayer) { handler(new (alloc) DrawLayerOp(mLayer), renderer.getSaveCount() - 1, properties().getClipToBounds()); } else { const int saveCountOffset = renderer.getSaveCount() - 1; const int projectionReceiveIndex = mDisplayList->projectionReceiveIndex; for (size_t chunkIndex = 0; chunkIndex < mDisplayList->getChunks().size(); chunkIndex++) { const DisplayList::Chunk& chunk = mDisplayList->getChunks()[chunkIndex]; std::vector<ZDrawRenderNodeOpPair> zTranslatedNodes; buildZSortedChildList(chunk, zTranslatedNodes); issueOperationsOf3dChildren(ChildrenSelectMode::NegativeZChildren, initialTransform, zTranslatedNodes, renderer, handler); for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) { DisplayListOp *op = mDisplayList->getOps()[opIndex]; #if DEBUG_DISPLAY_LIST op->output(handler.level() + 1); #endif handler(op, saveCountOffset, properties().getClipToBounds()); if (CC_UNLIKELY(!mProjectedNodes.empty() && projectionReceiveIndex >= 0 && opIndex == static_cast<size_t>(projectionReceiveIndex))) { issueOperationsOfProjectedChildren(renderer, handler); } } issueOperationsOf3dChildren(ChildrenSelectMode::PositiveZChildren, initialTransform, zTranslatedNodes, renderer, handler); } } } #endif DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (handler.level() + 1) * 2, "", restoreTo); handler(new (alloc) RestoreToCountOp(restoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds()); DISPLAY_LIST_LOGD("%*sDone (%p, %s)", handler.level() * 2, "", this, getName()); handler.endMark(); }