/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H #define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H #include #include #include #include #include "DisplayListLogBuffer.h" #include "RenderNode.h" #include "ResourceCache.h" namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////// // Debug #if DEBUG_DISPLAY_LIST #define DISPLAY_LIST_LOGD(...) ALOGD(__VA_ARGS__) #else #define DISPLAY_LIST_LOGD(...) #endif /////////////////////////////////////////////////////////////////////////////// // Display list /////////////////////////////////////////////////////////////////////////////// class DeferredDisplayList; class DeferredLayerUpdater; class DisplayListRenderer; class DisplayListOp; class DrawOp; class StateOp; /** * Records drawing commands in a display list for later playback into an OpenGLRenderer. */ class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer { public: DisplayListRenderer(); virtual ~DisplayListRenderer(); void insertReorderBarrier(bool enableReorder); DisplayListData* finishRecording(); // ---------------------------------------------------------------------------- // Frame state operations // ---------------------------------------------------------------------------- virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); virtual void interrupt(); virtual void resume(); // ---------------------------------------------------------------------------- // Canvas state operations // ---------------------------------------------------------------------------- // Save (layer) virtual int save(int flags); virtual void restore(); virtual void restoreToCount(int saveCount); virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint, int flags); // Matrix virtual void translate(float dx, float dy, float dz = 0.0f); virtual void rotate(float degrees); virtual void scale(float sx, float sy); virtual void skew(float sx, float sy); virtual void setMatrix(const SkMatrix& matrix); virtual void concatMatrix(const SkMatrix& matrix); // Clip virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool clipPath(const SkPath* path, SkRegion::Op op); virtual bool clipRegion(const SkRegion* region, SkRegion::Op op); // Misc - should be implemented with SkPaint inspection virtual void resetPaintFilter(); virtual void setupPaintFilter(int clearBits, int setBits); bool isCurrentTransformSimple() { return currentTransform()->isSimple(); } // ---------------------------------------------------------------------------- // Canvas draw operations // ---------------------------------------------------------------------------- virtual status_t drawColor(int color, SkXfermode::Mode mode); // Bitmap-based virtual status_t drawBitmap(const SkBitmap* bitmap, const SkPaint* paint); virtual status_t drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint); virtual status_t drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint); virtual status_t drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight, const float* vertices, const int* colors, const SkPaint* paint); virtual status_t drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch, float left, float top, float right, float bottom, const SkPaint* paint); // Shapes virtual status_t drawRect(float left, float top, float right, float bottom, const SkPaint* paint); virtual status_t drawRects(const float* rects, int count, const SkPaint* paint); virtual status_t drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const SkPaint* paint); virtual status_t drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top, CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom, CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry, CanvasPropertyPaint* paint); virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint); virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y, CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint); virtual status_t drawOval(float left, float top, float right, float bottom, const SkPaint* paint); virtual status_t drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint); virtual status_t drawPath(const SkPath* path, const SkPaint* paint); virtual status_t drawLines(const float* points, int count, const SkPaint* paint); virtual status_t drawPoints(const float* points, int count, const SkPaint* paint); // Text virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y, const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode = kDrawOpMode_Immediate); virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path, float hOffset, float vOffset, const SkPaint* paint); virtual status_t drawPosText(const char* text, int bytesCount, int count, const float* positions, const SkPaint* paint); // ---------------------------------------------------------------------------- // Canvas draw operations - special // ---------------------------------------------------------------------------- virtual status_t drawLayer(DeferredLayerUpdater* layerHandle, float x, float y); virtual status_t drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags); // TODO: rename for consistency virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty); void setHighContrastText(bool highContrastText) { mHighContrastText = highContrastText; } private: enum DeferredBarrierType { kBarrier_None, kBarrier_InOrder, kBarrier_OutOfOrder, }; void flushRestoreToCount(); void flushTranslate(); void flushReorderBarrier(); LinearAllocator& alloc() { return mDisplayListData->allocator; } // Each method returns final index of op size_t addOpAndUpdateChunk(DisplayListOp* op); // flushes any deferred operations, and appends the op size_t flushAndAddOp(DisplayListOp* op); size_t addStateOp(StateOp* op); size_t addDrawOp(DrawOp* op); size_t addRenderNodeOp(DrawRenderNodeOp* op); template inline const T* refBuffer(const T* srcBuffer, int32_t count) { if (!srcBuffer) return NULL; T* dstBuffer = (T*) mDisplayListData->allocator.alloc(count * sizeof(T)); memcpy(dstBuffer, srcBuffer, count * sizeof(T)); return dstBuffer; } inline char* refText(const char* text, size_t byteLength) { return (char*) refBuffer((uint8_t*)text, byteLength); } inline const SkPath* refPath(const SkPath* path) { if (!path) return NULL; const SkPath* pathCopy = mPathMap.valueFor(path); if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) { SkPath* newPathCopy = new SkPath(*path); newPathCopy->setSourcePath(path); pathCopy = newPathCopy; // replaceValueFor() performs an add if the entry doesn't exist mPathMap.replaceValueFor(path, pathCopy); mDisplayListData->paths.add(pathCopy); } if (mDisplayListData->sourcePaths.indexOf(path) < 0) { mResourceCache.incrementRefcount(path); mDisplayListData->sourcePaths.add(path); } return pathCopy; } inline const SkPaint* refPaint(const SkPaint* paint) { if (!paint) return NULL; const SkPaint* paintCopy = mPaintMap.valueFor(paint); if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID() // We can't compare shader pointers because that will always // change as we do partial copying via wrapping. However, if the // shader changes the paint generationID will have changed and // so we don't hit this comparison anyway || !(paint->getShader() && paintCopy->getShader() && paint->getShader()->getGenerationID() == paintCopy->getShader()->getGenerationID())) { paintCopy = copyPaint(paint); // replaceValueFor() performs an add if the entry doesn't exist mPaintMap.replaceValueFor(paint, paintCopy); } return paintCopy; } inline SkPaint* copyPaint(const SkPaint* paint) { if (!paint) return NULL; SkPaint* paintCopy = new SkPaint(*paint); if (paint->getShader()) { SkShader* shaderCopy = SkShader::CreateLocalMatrixShader( paint->getShader(), paint->getShader()->getLocalMatrix()); paintCopy->setShader(shaderCopy); paintCopy->setGenerationID(paint->getGenerationID()); shaderCopy->setGenerationID(paint->getShader()->getGenerationID()); shaderCopy->unref(); } mDisplayListData->paints.add(paintCopy); return paintCopy; } inline const SkRegion* refRegion(const SkRegion* region) { if (!region) { return region; } const SkRegion* regionCopy = mRegionMap.valueFor(region); // TODO: Add generation ID to SkRegion if (regionCopy == NULL) { regionCopy = new SkRegion(*region); // replaceValueFor() performs an add if the entry doesn't exist mRegionMap.replaceValueFor(region, regionCopy); mDisplayListData->regions.add(regionCopy); } return regionCopy; } inline const SkBitmap* refBitmap(const SkBitmap* bitmap) { // Note that this assumes the bitmap is immutable. There are cases this won't handle // correctly, such as creating the bitmap from scratch, drawing with it, changing its // contents, and drawing again. The only fix would be to always copy it the first time, // which doesn't seem worth the extra cycles for this unlikely case. mDisplayListData->bitmapResources.add(bitmap); mResourceCache.incrementRefcount(bitmap); return bitmap; } inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) { mDisplayListData->ownedBitmapResources.add(bitmap); mResourceCache.incrementRefcount(bitmap); return bitmap; } inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) { mDisplayListData->patchResources.add(patch); mResourceCache.incrementRefcount(patch); return patch; } DefaultKeyedVector mPaintMap; DefaultKeyedVector mPathMap; DefaultKeyedVector mRegionMap; ResourceCache& mResourceCache; DisplayListData* mDisplayListData; float mTranslateX; float mTranslateY; bool mHasDeferredTranslate; DeferredBarrierType mDeferredBarrierType; bool mHighContrastText; int mRestoreSaveCount; friend class RenderNode; }; // class DisplayListRenderer }; // namespace uirenderer }; // namespace android #endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H