/*
* Copyright (C) 2015 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.
*/
#pragma once
#include "BakedOpState.h"
#include "Matrix.h"
#include "utils/Macros.h"
namespace android {
namespace uirenderer {
class Caches;
struct Glop;
class Layer;
class RenderState;
struct ClipBase;
/**
* Main rendering manager for a collection of work - one frame + any contained FBOs.
*
* Manages frame and FBO lifecycle, binding the GL framebuffer as appropriate. This is the only
* place where FBOs are bound, created, and destroyed.
*
* All rendering operations will be sent by the Dispatcher, a collection of static methods,
* which has intentionally limited access to the renderer functionality.
*/
class BakedOpRenderer {
public:
typedef void (*GlopReceiver)(BakedOpRenderer&, const Rect*, const ClipBase*, const Glop&);
/**
* Position agnostic shadow lighting info. Used with all shadow ops in scene.
*/
struct LightInfo {
LightInfo() : LightInfo(0, 0) {}
LightInfo(uint8_t ambientShadowAlpha,
uint8_t spotShadowAlpha)
: ambientShadowAlpha(ambientShadowAlpha)
, spotShadowAlpha(spotShadowAlpha) {}
uint8_t ambientShadowAlpha;
uint8_t spotShadowAlpha;
};
BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque,
const LightInfo& lightInfo)
: mGlopReceiver(DefaultGlopReceiver)
, mRenderState(renderState)
, mCaches(caches)
, mOpaque(opaque)
, mLightInfo(lightInfo) {
}
RenderState& renderState() { return mRenderState; }
Caches& caches() { return mCaches; }
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect);
void endFrame(const Rect& repaintRect);
WARN_UNUSED_RESULT OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height);
void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer);
void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect);
void endLayer();
WARN_UNUSED_RESULT OffscreenBuffer* copyToLayer(const Rect& area);
Texture* getTexture(const SkBitmap* bitmap);
const LightInfo& getLightInfo() const { return mLightInfo; }
void renderGlop(const BakedOpState& state, const Glop& glop) {
renderGlop(&state.computedState.clippedBounds,
state.computedState.getClipIfNeeded(),
glop);
}
void renderFunctor(const FunctorOp& op, const BakedOpState& state);
void renderGlop(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop) {
mGlopReceiver(*this, dirtyBounds, clip, glop);
}
bool offscreenRenderTarget() { return mRenderTarget.offscreenBuffer != nullptr; }
void dirtyRenderTarget(const Rect& dirtyRect);
bool didDraw() const { return mHasDrawn; }
uint32_t getViewportWidth() const { return mRenderTarget.viewportWidth; }
uint32_t getViewportHeight() const { return mRenderTarget.viewportHeight; }
// simple draw methods, to be used for end frame decoration
void drawRect(float left, float top, float right, float bottom, const SkPaint* paint) {
float ltrb[4] = { left, top, right, bottom };
drawRects(ltrb, 4, paint);
}
void drawRects(const float* rects, int count, const SkPaint* paint);
protected:
GlopReceiver mGlopReceiver;
private:
static void DefaultGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds,
const ClipBase* clip, const Glop& glop) {
renderer.renderGlopImpl(dirtyBounds, clip, glop);
}
void renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop);
void setViewport(uint32_t width, uint32_t height);
void clearColorBuffer(const Rect& clearRect);
void prepareRender(const Rect* dirtyBounds, const ClipBase* clip);
void setupStencilRectList(const ClipBase* clip);
void setupStencilRegion(const ClipBase* clip);
void setupStencilQuads(std::vector<Vertex>& quadVertices, int incrementThreshold);
RenderState& mRenderState;
Caches& mCaches;
bool mOpaque;
bool mHasDrawn = false;
// render target state - setup by start/end layer/frame
// only valid to use in between start/end pairs.
struct {
// If not drawing to a layer: fbo = 0, offscreenBuffer = null,
// Otherwise these refer to currently painting layer's state
GLuint frameBufferId = 0;
OffscreenBuffer* offscreenBuffer = nullptr;
// Used when drawing to a layer and using stencil clipping. otherwise null.
RenderBuffer* stencil = nullptr;
// value representing the ClipRectList* or ClipRegion* currently stored in
// the stencil of the current render target
const ClipBase* lastStencilClip = nullptr;
// Size of renderable region in current render target - for layers, may not match actual
// bounds of FBO texture. offscreenBuffer->texture has this information.
uint32_t viewportWidth = 0;
uint32_t viewportHeight = 0;
Matrix4 orthoMatrix;
} mRenderTarget;
const LightInfo mLightInfo;
};
}; // namespace uirenderer
}; // namespace android