Refactor blending and texture gl state
Change-Id: Ia6b3c8b2afd3dfcee7f3ce401d846b789612054a
This commit is contained in:
@@ -7,11 +7,13 @@ LOCAL_CLANG_CFLAGS += \
|
||||
LOCAL_SRC_FILES := \
|
||||
font/CacheTexture.cpp \
|
||||
font/Font.cpp \
|
||||
renderstate/Blend.cpp \
|
||||
renderstate/MeshState.cpp \
|
||||
renderstate/PixelBufferState.cpp \
|
||||
renderstate/RenderState.cpp \
|
||||
renderstate/Scissor.cpp \
|
||||
renderstate/Stencil.cpp \
|
||||
renderstate/TextureState.cpp \
|
||||
renderthread/CanvasContext.cpp \
|
||||
renderthread/DrawFrameTask.cpp \
|
||||
renderthread/EglManager.cpp \
|
||||
|
||||
@@ -49,6 +49,7 @@ Caches* Caches::sInstance = nullptr;
|
||||
|
||||
Caches::Caches(RenderState& renderState)
|
||||
: patchCache(renderState)
|
||||
, dither(*this)
|
||||
, mRenderState(&renderState)
|
||||
, mExtensions(Extensions::getInstance())
|
||||
, mInitialized(false) {
|
||||
@@ -71,13 +72,8 @@ bool Caches::init() {
|
||||
|
||||
ATRACE_NAME("Caches::init");
|
||||
|
||||
glActiveTexture(gTextureUnits[0]);
|
||||
mTextureUnit = 0;
|
||||
|
||||
mRegionMesh = nullptr;
|
||||
blend = false;
|
||||
lastSrcMode = GL_ZERO;
|
||||
lastDstMode = GL_ZERO;
|
||||
currentProgram = nullptr;
|
||||
|
||||
mFunctorsCount = 0;
|
||||
@@ -90,8 +86,8 @@ bool Caches::init() {
|
||||
|
||||
mInitialized = true;
|
||||
|
||||
resetBoundTextures();
|
||||
mPixelBufferState.reset(new PixelBufferState());
|
||||
mPixelBufferState = new PixelBufferState();
|
||||
mTextureState = new TextureState();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -122,12 +118,6 @@ void Caches::initExtensions() {
|
||||
}
|
||||
|
||||
void Caches::initConstraints() {
|
||||
GLint maxTextureUnits;
|
||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
|
||||
if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
|
||||
ALOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
|
||||
}
|
||||
|
||||
@@ -216,8 +206,10 @@ void Caches::terminate() {
|
||||
|
||||
clearGarbage();
|
||||
|
||||
mPixelBufferState.release();
|
||||
|
||||
delete mPixelBufferState;
|
||||
mPixelBufferState = nullptr;
|
||||
delete mTextureState;
|
||||
mTextureState = nullptr;
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
@@ -347,70 +339,6 @@ void Caches::flush(FlushMode mode) {
|
||||
glFinish();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Textures
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Caches::activeTexture(GLuint textureUnit) {
|
||||
if (mTextureUnit != textureUnit) {
|
||||
glActiveTexture(gTextureUnits[textureUnit]);
|
||||
mTextureUnit = textureUnit;
|
||||
}
|
||||
}
|
||||
|
||||
void Caches::resetActiveTexture() {
|
||||
mTextureUnit = -1;
|
||||
}
|
||||
|
||||
void Caches::bindTexture(GLuint texture) {
|
||||
if (mBoundTextures[mTextureUnit] != texture) {
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
mBoundTextures[mTextureUnit] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
void Caches::bindTexture(GLenum target, GLuint texture) {
|
||||
if (target == GL_TEXTURE_2D) {
|
||||
bindTexture(texture);
|
||||
} else {
|
||||
// GLConsumer directly calls glBindTexture() with
|
||||
// target=GL_TEXTURE_EXTERNAL_OES, don't cache this target
|
||||
// since the cached state could be stale
|
||||
glBindTexture(target, texture);
|
||||
}
|
||||
}
|
||||
|
||||
void Caches::deleteTexture(GLuint texture) {
|
||||
// When glDeleteTextures() is called on a currently bound texture,
|
||||
// OpenGL ES specifies that the texture is then considered unbound
|
||||
// Consider the following series of calls:
|
||||
//
|
||||
// glGenTextures -> creates texture name 2
|
||||
// glBindTexture(2)
|
||||
// glDeleteTextures(2) -> 2 is now unbound
|
||||
// glGenTextures -> can return 2 again
|
||||
//
|
||||
// If we don't call glBindTexture(2) after the second glGenTextures
|
||||
// call, any texture operation will be performed on the default
|
||||
// texture (name=0)
|
||||
|
||||
unbindTexture(texture);
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
|
||||
void Caches::resetBoundTextures() {
|
||||
memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint));
|
||||
}
|
||||
|
||||
void Caches::unbindTexture(GLuint texture) {
|
||||
for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
|
||||
if (mBoundTextures[i] == texture) {
|
||||
mBoundTextures[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Tiling
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "PathCache.h"
|
||||
#include "RenderBufferCache.h"
|
||||
#include "renderstate/PixelBufferState.h"
|
||||
#include "renderstate/TextureState.h"
|
||||
#include "ResourceCache.h"
|
||||
#include "TessellationCache.h"
|
||||
#include "TextDropShadowCache.h"
|
||||
@@ -58,20 +59,6 @@ namespace uirenderer {
|
||||
|
||||
class GammaFontRenderer;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Globals
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GL ES 2.0 defines that at least 16 texture units must be supported
|
||||
#define REQUIRED_TEXTURE_UNITS_COUNT 3
|
||||
|
||||
// Must define as many texture units as specified by REQUIRED_TEXTURE_UNITS_COUNT
|
||||
static const GLenum gTextureUnits[] = {
|
||||
GL_TEXTURE0,
|
||||
GL_TEXTURE1,
|
||||
GL_TEXTURE2
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Caches
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -155,49 +142,6 @@ public:
|
||||
void deleteLayerDeferred(Layer* layer);
|
||||
|
||||
|
||||
/**
|
||||
* Activate the specified texture unit. The texture unit must
|
||||
* be specified using an integer number (0 for GL_TEXTURE0 etc.)
|
||||
*/
|
||||
void activeTexture(GLuint textureUnit);
|
||||
|
||||
/**
|
||||
* Invalidate the cached value of the active texture unit.
|
||||
*/
|
||||
void resetActiveTexture();
|
||||
|
||||
/**
|
||||
* Binds the specified texture as a GL_TEXTURE_2D texture.
|
||||
* All texture bindings must be performed with this method or
|
||||
* bindTexture(GLenum, GLuint).
|
||||
*/
|
||||
void bindTexture(GLuint texture);
|
||||
|
||||
/**
|
||||
* Binds the specified texture with the specified render target.
|
||||
* All texture bindings must be performed with this method or
|
||||
* bindTexture(GLuint).
|
||||
*/
|
||||
void bindTexture(GLenum target, GLuint texture);
|
||||
|
||||
/**
|
||||
* Deletes the specified texture and clears it from the cache
|
||||
* of bound textures.
|
||||
* All textures must be deleted using this method.
|
||||
*/
|
||||
void deleteTexture(GLuint texture);
|
||||
|
||||
/**
|
||||
* Signals that the cache of bound textures should be cleared.
|
||||
* Other users of the context may have altered which textures are bound.
|
||||
*/
|
||||
void resetBoundTextures();
|
||||
|
||||
/**
|
||||
* Clear the cache of bound textures.
|
||||
*/
|
||||
void unbindTexture(GLuint texture);
|
||||
|
||||
void startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard);
|
||||
void endTiling();
|
||||
|
||||
@@ -218,9 +162,6 @@ public:
|
||||
void registerFunctors(uint32_t functorCount);
|
||||
void unregisterFunctors(uint32_t functorCount);
|
||||
|
||||
bool blend;
|
||||
GLenum lastSrcMode;
|
||||
GLenum lastDstMode;
|
||||
Program* currentProgram;
|
||||
|
||||
bool drawDeferDisabled;
|
||||
@@ -278,7 +219,8 @@ public:
|
||||
int propertyAmbientShadowStrength;
|
||||
int propertySpotShadowStrength;
|
||||
|
||||
PixelBufferState& pixelBuffer() { return *mPixelBufferState; }
|
||||
PixelBufferState& pixelBufferState() { return *mPixelBufferState; }
|
||||
TextureState& textureState() { return *mTextureState; }
|
||||
|
||||
private:
|
||||
enum OverdrawColorSet {
|
||||
@@ -305,9 +247,8 @@ private:
|
||||
|
||||
RenderState* mRenderState;
|
||||
|
||||
std::unique_ptr<PixelBufferState> mPixelBufferState; // TODO: move to RenderState
|
||||
|
||||
GLuint mTextureUnit;
|
||||
PixelBufferState* mPixelBufferState = nullptr; // TODO: move to RenderState
|
||||
TextureState* mTextureState = nullptr; // TODO: move to RenderState
|
||||
|
||||
Extensions& mExtensions;
|
||||
|
||||
@@ -322,9 +263,6 @@ private:
|
||||
|
||||
uint32_t mFunctorsCount;
|
||||
|
||||
// Caches texture bindings for the GL_TEXTURE_2D target
|
||||
GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
|
||||
|
||||
OverdrawColorSet mOverdrawDebugColorSet;
|
||||
}; // class Caches
|
||||
|
||||
|
||||
@@ -24,7 +24,10 @@ namespace uirenderer {
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Dither::Dither(): mCaches(nullptr), mInitialized(false), mDitherTexture(0) {
|
||||
Dither::Dither(Caches& caches)
|
||||
: mCaches(caches)
|
||||
, mInitialized(false)
|
||||
, mDitherTexture(0) {
|
||||
}
|
||||
|
||||
void Dither::bindDitherTexture() {
|
||||
@@ -32,7 +35,7 @@ void Dither::bindDitherTexture() {
|
||||
bool useFloatTexture = Extensions::getInstance().hasFloatTextures();
|
||||
|
||||
glGenTextures(1, &mDitherTexture);
|
||||
mCaches->bindTexture(mDitherTexture);
|
||||
mCaches.textureState().bindTexture(mDitherTexture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
@@ -71,13 +74,13 @@ void Dither::bindDitherTexture() {
|
||||
|
||||
mInitialized = true;
|
||||
} else {
|
||||
mCaches->bindTexture(mDitherTexture);
|
||||
mCaches.textureState().bindTexture(mDitherTexture);
|
||||
}
|
||||
}
|
||||
|
||||
void Dither::clear() {
|
||||
if (mInitialized) {
|
||||
mCaches->deleteTexture(mDitherTexture);
|
||||
mCaches.textureState().deleteTexture(mDitherTexture);
|
||||
mInitialized = false;
|
||||
}
|
||||
}
|
||||
@@ -87,10 +90,8 @@ void Dither::clear() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Dither::setupProgram(Program* program, GLuint* textureUnit) {
|
||||
if (!mCaches) mCaches = &Caches::getInstance();
|
||||
|
||||
GLuint textureSlot = (*textureUnit)++;
|
||||
mCaches->activeTexture(textureSlot);
|
||||
mCaches.textureState().activateTexture(textureSlot);
|
||||
|
||||
bindDitherTexture();
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class Program;
|
||||
*/
|
||||
class Dither {
|
||||
public:
|
||||
Dither();
|
||||
Dither(Caches& caches);
|
||||
|
||||
void clear();
|
||||
void setupProgram(Program* program, GLuint* textureUnit);
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
private:
|
||||
void bindDitherTexture();
|
||||
|
||||
Caches* mCaches;
|
||||
Caches& mCaches;
|
||||
bool mInitialized;
|
||||
GLuint mDitherTexture;
|
||||
};
|
||||
|
||||
@@ -284,7 +284,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
|
||||
uint32_t cacheWidth = cacheTexture->getWidth();
|
||||
|
||||
if (!cacheTexture->getPixelBuffer()) {
|
||||
Caches::getInstance().activeTexture(0);
|
||||
Caches::getInstance().textureState().activateTexture(0);
|
||||
// Large-glyph texture memory is allocated only as needed
|
||||
cacheTexture->allocateTexture();
|
||||
}
|
||||
@@ -397,7 +397,7 @@ CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum for
|
||||
CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads);
|
||||
|
||||
if (allocate) {
|
||||
Caches::getInstance().activeTexture(0);
|
||||
Caches::getInstance().textureState().activateTexture(0);
|
||||
cacheTexture->allocateTexture();
|
||||
cacheTexture->allocateMesh();
|
||||
}
|
||||
@@ -443,8 +443,8 @@ void checkTextureUpdateForCache(Caches& caches, Vector<CacheTexture*>& cacheText
|
||||
if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) {
|
||||
if (cacheTexture->getTextureId() != lastTextureId) {
|
||||
lastTextureId = cacheTexture->getTextureId();
|
||||
caches.activeTexture(0);
|
||||
caches.bindTexture(lastTextureId);
|
||||
caches.textureState().activateTexture(0);
|
||||
caches.textureState().bindTexture(lastTextureId);
|
||||
}
|
||||
|
||||
if (cacheTexture->upload()) {
|
||||
@@ -470,7 +470,7 @@ void FontRenderer::checkTextureUpdate() {
|
||||
checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId);
|
||||
|
||||
// Unbind any PBO we might have used to update textures
|
||||
caches.pixelBuffer().unbind();
|
||||
caches.pixelBufferState().unbind();
|
||||
|
||||
// Reset to default unpack row length to avoid affecting texture
|
||||
// uploads in other parts of the renderer
|
||||
@@ -507,11 +507,11 @@ void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
|
||||
forceRebind = renderState.meshState().unbindMeshBuffer();
|
||||
}
|
||||
|
||||
caches.activeTexture(0);
|
||||
caches.textureState().activateTexture(0);
|
||||
first = false;
|
||||
}
|
||||
|
||||
caches.bindTexture(texture->getTextureId());
|
||||
caches.textureState().bindTexture(texture->getTextureId());
|
||||
texture->setLinearFiltering(mLinearFiltering, false);
|
||||
|
||||
TextureVertex* mesh = texture->mesh();
|
||||
@@ -649,7 +649,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co
|
||||
Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, nullptr, positions);
|
||||
|
||||
// Unbind any PBO we might have used
|
||||
Caches::getInstance().pixelBuffer().unbind();
|
||||
Caches::getInstance().pixelBufferState().unbind();
|
||||
|
||||
blurImage(&dataBuffer, paddedWidth, paddedHeight, radius);
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ void GradientCache::generateTexture(uint32_t* colors, float* positions, Texture*
|
||||
memcpy(pixels + rowBytes, pixels, rowBytes);
|
||||
|
||||
glGenTextures(1, &texture->id);
|
||||
Caches::getInstance().bindTexture(texture->id);
|
||||
Caches::getInstance().textureState().bindTexture(texture->id);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
if (mUseFloatTexture) {
|
||||
|
||||
@@ -39,7 +39,7 @@ Image::Image(sp<GraphicBuffer> buffer) {
|
||||
} else {
|
||||
// Create a 2D texture to sample from the EGLImage
|
||||
glGenTextures(1, &mTexture);
|
||||
Caches::getInstance().bindTexture(mTexture);
|
||||
Caches::getInstance().textureState().bindTexture(mTexture);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage);
|
||||
|
||||
GLenum status = GL_NO_ERROR;
|
||||
@@ -54,7 +54,7 @@ Image::~Image() {
|
||||
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), mImage);
|
||||
mImage = EGL_NO_IMAGE_KHR;
|
||||
|
||||
Caches::getInstance().deleteTexture(mTexture);
|
||||
Caches::getInstance().textureState().deleteTexture(mTexture);
|
||||
mTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ bool Layer::resize(const uint32_t width, const uint32_t height) {
|
||||
setSize(desiredWidth, desiredHeight);
|
||||
|
||||
if (fbo) {
|
||||
caches.activeTexture(0);
|
||||
caches.textureState().activateTexture(0);
|
||||
bindTexture();
|
||||
allocateTexture();
|
||||
|
||||
@@ -195,7 +195,7 @@ void Layer::setColorFilter(SkColorFilter* filter) {
|
||||
|
||||
void Layer::bindTexture() const {
|
||||
if (texture.id) {
|
||||
caches.bindTexture(renderTarget, texture.id);
|
||||
caches.textureState().bindTexture(renderTarget, texture.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ void Layer::deleteTexture() {
|
||||
}
|
||||
|
||||
void Layer::clearTexture() {
|
||||
caches.unbindTexture(texture.id);
|
||||
caches.textureState().unbindTexture(texture.id);
|
||||
texture.id = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
caches.activeTexture(0);
|
||||
caches.textureState().activateTexture(0);
|
||||
Layer* layer = caches.layerCache.get(renderState, width, height);
|
||||
if (!layer) {
|
||||
ALOGW("Could not obtain a layer");
|
||||
@@ -283,7 +283,7 @@ Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
|
||||
layer->region.clear();
|
||||
layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer()
|
||||
|
||||
Caches::getInstance().activeTexture(0);
|
||||
Caches::getInstance().textureState().activateTexture(0);
|
||||
layer->generateTexture();
|
||||
|
||||
return layer;
|
||||
@@ -412,8 +412,8 @@ bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap*
|
||||
glGenTextures(1, &texture);
|
||||
if ((error = glGetError()) != GL_NO_ERROR) goto error;
|
||||
|
||||
caches.activeTexture(0);
|
||||
caches.bindTexture(texture);
|
||||
caches.textureState().activateTexture(0);
|
||||
caches.textureState().bindTexture(texture);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
|
||||
|
||||
@@ -475,7 +475,7 @@ error:
|
||||
renderState.bindFramebuffer(previousFbo);
|
||||
layer->setAlpha(alpha, mode);
|
||||
layer->setFbo(previousLayerFbo);
|
||||
caches.deleteTexture(texture);
|
||||
caches.textureState().deleteTexture(texture);
|
||||
caches.fboCache.put(fbo);
|
||||
renderState.setViewport(previousViewportWidth, previousViewportHeight);
|
||||
|
||||
|
||||
@@ -71,55 +71,6 @@ static GLenum getFilter(const SkPaint* paint) {
|
||||
// Globals
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Structure mapping Skia xfermodes to OpenGL blending factors.
|
||||
*/
|
||||
struct Blender {
|
||||
SkXfermode::Mode mode;
|
||||
GLenum src;
|
||||
GLenum dst;
|
||||
}; // struct Blender
|
||||
|
||||
// In this array, the index of each Blender equals the value of the first
|
||||
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
|
||||
static const Blender gBlends[] = {
|
||||
{ SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
|
||||
{ SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
|
||||
{ SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
|
||||
{ SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
|
||||
{ SkXfermode::kModulate_Mode, GL_ZERO, GL_SRC_COLOR },
|
||||
{ SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
|
||||
};
|
||||
|
||||
// This array contains the swapped version of each SkXfermode. For instance
|
||||
// this array's SrcOver blending mode is actually DstOver. You can refer to
|
||||
// createLayer() for more information on the purpose of this array.
|
||||
static const Blender gBlendsSwap[] = {
|
||||
{ SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
|
||||
{ SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
|
||||
{ SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
|
||||
{ SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
|
||||
{ SkXfermode::kModulate_Mode, GL_DST_COLOR, GL_ZERO },
|
||||
{ SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Functions
|
||||
@@ -234,7 +185,7 @@ void OpenGLRenderer::prepareDirty(float left, float top,
|
||||
// for each layer and wait until the first drawing command
|
||||
// to start the frame
|
||||
if (currentSnapshot()->fbo == 0) {
|
||||
syncState();
|
||||
mRenderState.blend().syncEnabled();
|
||||
updateLayers();
|
||||
} else {
|
||||
startFrame();
|
||||
@@ -267,14 +218,6 @@ void OpenGLRenderer::clear(float left, float top, float right, float bottom, boo
|
||||
mRenderState.scissor().reset();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::syncState() {
|
||||
if (mCaches.blend) {
|
||||
glEnable(GL_BLEND);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::startTilingCurrentClip(bool opaque, bool expand) {
|
||||
if (!mSuppressTiling) {
|
||||
const Snapshot* snapshot = currentSnapshot();
|
||||
@@ -559,7 +502,7 @@ void OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
|
||||
|
||||
void OpenGLRenderer::flushLayerUpdates() {
|
||||
ATRACE_NAME("Update HW Layers");
|
||||
syncState();
|
||||
mRenderState.blend().syncEnabled();
|
||||
updateLayers();
|
||||
flushLayers();
|
||||
// Wait for all the layer updates to be executed
|
||||
@@ -756,7 +699,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
|
||||
return false;
|
||||
}
|
||||
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
|
||||
if (!layer) {
|
||||
return false;
|
||||
@@ -896,7 +839,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
|
||||
|
||||
mRenderState.meshState().unbindMeshBuffer();
|
||||
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
|
||||
// When the layer is stored in an FBO, we can save a bit of fillrate by
|
||||
// drawing only the dirty region
|
||||
@@ -1898,13 +1841,13 @@ void OpenGLRenderer::setupDrawSimpleMesh() {
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawTexture(GLuint texture) {
|
||||
if (texture) bindTexture(texture);
|
||||
if (texture) mCaches.textureState().bindTexture(texture);
|
||||
mTextureUnit++;
|
||||
mRenderState.meshState().enableTexCoordsVertexArray();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
|
||||
bindExternalTexture(texture);
|
||||
mCaches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
|
||||
mTextureUnit++;
|
||||
mRenderState.meshState().enableTexCoordsVertexArray();
|
||||
}
|
||||
@@ -2050,7 +1993,7 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top,
|
||||
void OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
|
||||
int bitmapCount, TextureVertex* vertices, bool pureTranslate,
|
||||
const Rect& bounds, const SkPaint* paint) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
|
||||
if (!texture) return;
|
||||
|
||||
@@ -2081,7 +2024,7 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
Texture* texture = getTexture(bitmap);
|
||||
if (!texture) return;
|
||||
const AutoTexture autoCleanup(texture);
|
||||
@@ -2122,7 +2065,7 @@ void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int m
|
||||
colors = tempColors.get();
|
||||
}
|
||||
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap);
|
||||
const UvMapper& mapper(getMapper(texture));
|
||||
|
||||
@@ -2217,7 +2160,7 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap,
|
||||
return;
|
||||
}
|
||||
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
Texture* texture = getTexture(bitmap);
|
||||
if (!texture) return;
|
||||
const AutoTexture autoCleanup(texture);
|
||||
@@ -2317,7 +2260,7 @@ void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
|
||||
}
|
||||
|
||||
if (CC_LIKELY(mesh && mesh->verticesCount > 0)) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
|
||||
if (!texture) return;
|
||||
const AutoTexture autoCleanup(texture);
|
||||
@@ -2371,7 +2314,7 @@ void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
|
||||
*/
|
||||
void OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
|
||||
TextureVertex* vertices, uint32_t indexCount, const SkPaint* paint) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
|
||||
if (!texture) return;
|
||||
const AutoTexture autoCleanup(texture);
|
||||
@@ -2556,7 +2499,7 @@ void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bot
|
||||
}
|
||||
|
||||
if (p->getPathEffect() != nullptr) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
const PathTexture* texture = mCaches.pathCache.getRoundRect(
|
||||
right - left, bottom - top, rx, ry, p);
|
||||
drawShape(left, top, texture, p);
|
||||
@@ -2574,7 +2517,7 @@ void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p
|
||||
return;
|
||||
}
|
||||
if (p->getPathEffect() != nullptr) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
const PathTexture* texture = mCaches.pathCache.getCircle(radius, p);
|
||||
drawShape(x - radius, y - radius, texture, p);
|
||||
} else {
|
||||
@@ -2597,7 +2540,7 @@ void OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
|
||||
}
|
||||
|
||||
if (p->getPathEffect() != nullptr) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
const PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p);
|
||||
drawShape(left, top, texture, p);
|
||||
} else {
|
||||
@@ -2621,7 +2564,7 @@ void OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
|
||||
|
||||
// TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
|
||||
if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != nullptr || useCenter) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
const PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top,
|
||||
startAngle, sweepAngle, useCenter, p);
|
||||
drawShape(left, top, texture, p);
|
||||
@@ -2658,7 +2601,7 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
|
||||
// only fill style is supported by drawConvexPath, since others have to handle joins
|
||||
if (p->getPathEffect() != nullptr || p->getStrokeJoin() != SkPaint::kMiter_Join ||
|
||||
p->getStrokeMiter() != SkPaintDefaults_MiterLimit) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
const PathTexture* texture =
|
||||
mCaches.pathCache.getRect(right - left, bottom - top, p);
|
||||
drawShape(left, top, texture, p);
|
||||
@@ -2687,7 +2630,7 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
|
||||
void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
|
||||
int bytesCount, int count, const float* positions,
|
||||
FontRenderer& fontRenderer, int alpha, float x, float y) {
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
|
||||
TextShadow textShadow;
|
||||
if (!getTextShadow(paint, &textShadow)) {
|
||||
@@ -3001,7 +2944,7 @@ void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
|
||||
void OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
|
||||
if (mState.currentlyIgnored()) return;
|
||||
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
|
||||
const PathTexture* texture = mCaches.pathCache.get(path, paint);
|
||||
if (!texture) return;
|
||||
@@ -3046,7 +2989,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
|
||||
updateLayer(layer, true);
|
||||
|
||||
mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
|
||||
mCaches.activeTexture(0);
|
||||
mCaches.textureState().activateTexture(0);
|
||||
|
||||
if (CC_LIKELY(!layer->region.isEmpty())) {
|
||||
if (layer->region.isRect()) {
|
||||
@@ -3485,33 +3428,16 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
|
||||
description.framebufferMode = mode;
|
||||
description.swapSrcDst = swapSrcDst;
|
||||
|
||||
if (mCaches.blend) {
|
||||
glDisable(GL_BLEND);
|
||||
mCaches.blend = false;
|
||||
}
|
||||
|
||||
mRenderState.blend().disable();
|
||||
return;
|
||||
} else {
|
||||
mode = SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mCaches.blend) {
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
GLenum sourceMode = swapSrcDst ? gBlendsSwap[mode].src : gBlends[mode].src;
|
||||
GLenum destMode = swapSrcDst ? gBlendsSwap[mode].dst : gBlends[mode].dst;
|
||||
|
||||
if (sourceMode != mCaches.lastSrcMode || destMode != mCaches.lastDstMode) {
|
||||
glBlendFunc(sourceMode, destMode);
|
||||
mCaches.lastSrcMode = sourceMode;
|
||||
mCaches.lastDstMode = destMode;
|
||||
}
|
||||
} else if (mCaches.blend) {
|
||||
glDisable(GL_BLEND);
|
||||
mRenderState.blend().enable(mode, swapSrcDst);
|
||||
} else {
|
||||
mRenderState.blend().disable();
|
||||
}
|
||||
mCaches.blend = blend;
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::useProgram(Program* program) {
|
||||
|
||||
@@ -540,12 +540,6 @@ private:
|
||||
*/
|
||||
void discardFramebuffer(float left, float top, float right, float bottom);
|
||||
|
||||
/**
|
||||
* Ensures the state of the renderer is the same as the state of
|
||||
* the GL context.
|
||||
*/
|
||||
void syncState();
|
||||
|
||||
/**
|
||||
* Tells the GPU what part of the screen is about to be redrawn.
|
||||
* This method will use the current layer space clip rect.
|
||||
@@ -851,22 +845,6 @@ private:
|
||||
*/
|
||||
bool canSkipText(const SkPaint* paint) const;
|
||||
|
||||
/**
|
||||
* Binds the specified texture. The texture unit must have been selected
|
||||
* prior to calling this method.
|
||||
*/
|
||||
inline void bindTexture(GLuint texture) {
|
||||
mCaches.bindTexture(texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the specified EGLImage texture. The texture unit must have been selected
|
||||
* prior to calling this method.
|
||||
*/
|
||||
inline void bindExternalTexture(GLuint texture) {
|
||||
mCaches.bindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable blending as necessary. This function sets the appropriate
|
||||
* blend function based on the specified xfermode.
|
||||
|
||||
@@ -230,7 +230,7 @@ void PathCache::removeTexture(PathTexture* texture) {
|
||||
}
|
||||
|
||||
if (texture->id) {
|
||||
Caches::getInstance().deleteTexture(texture->id);
|
||||
Caches::getInstance().textureState().deleteTexture(texture->id);
|
||||
}
|
||||
delete texture;
|
||||
}
|
||||
@@ -312,7 +312,7 @@ void PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) {
|
||||
|
||||
glGenTextures(1, &texture->id);
|
||||
|
||||
Caches::getInstance().bindTexture(texture->id);
|
||||
Caches::getInstance().textureState().bindTexture(texture->id);
|
||||
// Textures are Alpha8
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
|
||||
@@ -101,9 +101,9 @@ GpuPixelBuffer::GpuPixelBuffer(GLenum format,
|
||||
, mCaches(Caches::getInstance()){
|
||||
glGenBuffers(1, &mBuffer);
|
||||
|
||||
mCaches.pixelBuffer().bind(mBuffer);
|
||||
mCaches.pixelBufferState().bind(mBuffer);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
|
||||
mCaches.pixelBuffer().unbind();
|
||||
mCaches.pixelBufferState().unbind();
|
||||
}
|
||||
|
||||
GpuPixelBuffer::~GpuPixelBuffer() {
|
||||
@@ -112,7 +112,7 @@ GpuPixelBuffer::~GpuPixelBuffer() {
|
||||
|
||||
uint8_t* GpuPixelBuffer::map(AccessMode mode) {
|
||||
if (mAccessMode == kAccessMode_None) {
|
||||
mCaches.pixelBuffer().bind(mBuffer);
|
||||
mCaches.pixelBufferState().bind(mBuffer);
|
||||
mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
|
||||
#if DEBUG_OPENGL
|
||||
if (!mMappedPointer) {
|
||||
@@ -131,7 +131,7 @@ uint8_t* GpuPixelBuffer::map(AccessMode mode) {
|
||||
void GpuPixelBuffer::unmap() {
|
||||
if (mAccessMode != kAccessMode_None) {
|
||||
if (mMappedPointer) {
|
||||
mCaches.pixelBuffer().bind(mBuffer);
|
||||
mCaches.pixelBufferState().bind(mBuffer);
|
||||
GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
if (status == GL_FALSE) {
|
||||
ALOGE("Corrupted GPU pixel buffer");
|
||||
@@ -148,7 +148,7 @@ uint8_t* GpuPixelBuffer::getMappedPointer() const {
|
||||
|
||||
void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
|
||||
// If the buffer is not mapped, unmap() will not bind it
|
||||
mCaches.pixelBuffer().bind(mBuffer);
|
||||
mCaches.pixelBufferState().bind(mBuffer);
|
||||
unmap();
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
|
||||
GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
|
||||
|
||||
@@ -57,7 +57,7 @@ static inline void bindUniformColor(int slot, uint32_t color) {
|
||||
}
|
||||
|
||||
static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
|
||||
caches->bindTexture(texture->id);
|
||||
caches->textureState().bindTexture(texture->id);
|
||||
texture->setWrapST(wrapS, wrapT);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
|
||||
}
|
||||
|
||||
GLuint textureSlot = (*textureUnit)++;
|
||||
caches->activeTexture(textureSlot);
|
||||
caches->textureState().activateTexture(textureSlot);
|
||||
|
||||
const float width = layer->getWidth();
|
||||
const float height = layer->getHeight();
|
||||
@@ -270,7 +270,7 @@ void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
|
||||
}
|
||||
|
||||
GLuint textureSlot = (*textureUnit)++;
|
||||
Caches::getInstance().activeTexture(textureSlot);
|
||||
Caches::getInstance().textureState().activateTexture(textureSlot);
|
||||
|
||||
BitmapShaderInfo shaderInfo;
|
||||
if (!bitmapShaderHelper(caches, nullptr, &shaderInfo, extensions, bitmap, xy)) {
|
||||
@@ -392,7 +392,7 @@ void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatri
|
||||
shader.asAGradient(&gradInfo);
|
||||
}
|
||||
GLuint textureSlot = (*textureUnit)++;
|
||||
caches->activeTexture(textureSlot);
|
||||
caches->textureState().activateTexture(textureSlot);
|
||||
|
||||
#ifndef SK_SCALAR_IS_FLOAT
|
||||
#error Need to convert gradInfo.fColorOffsets to float!
|
||||
|
||||
@@ -207,7 +207,7 @@ ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const char* text,
|
||||
|
||||
glGenTextures(1, &texture->id);
|
||||
|
||||
caches.bindTexture(texture->id);
|
||||
caches.textureState().bindTexture(texture->id);
|
||||
// Textures are Alpha8
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
|
||||
@@ -24,18 +24,44 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
Texture::Texture(): id(0), generation(0), blend(false), width(0), height(0),
|
||||
cleanup(false), bitmapSize(0), mipMap(false), uvMapper(nullptr), isInUse(false),
|
||||
mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
|
||||
mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
|
||||
mFirstFilter(true), mFirstWrap(true), mCaches(Caches::getInstance()) {
|
||||
Texture::Texture()
|
||||
: id(0)
|
||||
, generation(0)
|
||||
, blend(false)
|
||||
, width(0)
|
||||
, height(0)
|
||||
, cleanup(false)
|
||||
, bitmapSize(0)
|
||||
, mipMap(false)
|
||||
, uvMapper(nullptr)
|
||||
, isInUse(false)
|
||||
, mWrapS(GL_CLAMP_TO_EDGE)
|
||||
, mWrapT(GL_CLAMP_TO_EDGE)
|
||||
, mMinFilter(GL_NEAREST)
|
||||
, mMagFilter(GL_NEAREST)
|
||||
, mFirstFilter(true)
|
||||
, mFirstWrap(true)
|
||||
, mCaches(Caches::getInstance()) {
|
||||
}
|
||||
|
||||
Texture::Texture(Caches& caches): id(0), generation(0), blend(false), width(0), height(0),
|
||||
cleanup(false), bitmapSize(0), mipMap(false), uvMapper(nullptr), isInUse(false),
|
||||
mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
|
||||
mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
|
||||
mFirstFilter(true), mFirstWrap(true), mCaches(caches) {
|
||||
Texture::Texture(Caches& caches)
|
||||
: id(0)
|
||||
, generation(0)
|
||||
, blend(false)
|
||||
, width(0)
|
||||
, height(0)
|
||||
, cleanup(false)
|
||||
, bitmapSize(0)
|
||||
, mipMap(false)
|
||||
, uvMapper(nullptr)
|
||||
, isInUse(false)
|
||||
, mWrapS(GL_CLAMP_TO_EDGE)
|
||||
, mWrapT(GL_CLAMP_TO_EDGE)
|
||||
, mMinFilter(GL_NEAREST)
|
||||
, mMagFilter(GL_NEAREST)
|
||||
, mFirstFilter(true)
|
||||
, mFirstWrap(true)
|
||||
, mCaches(caches) {
|
||||
}
|
||||
|
||||
void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force,
|
||||
@@ -48,7 +74,7 @@ void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force
|
||||
mWrapT = wrapT;
|
||||
|
||||
if (bindTexture) {
|
||||
mCaches.bindTexture(renderTarget, id);
|
||||
mCaches.textureState().bindTexture(renderTarget, id);
|
||||
}
|
||||
|
||||
glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
|
||||
@@ -66,7 +92,7 @@ void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool for
|
||||
mMagFilter = mag;
|
||||
|
||||
if (bindTexture) {
|
||||
mCaches.bindTexture(renderTarget, id);
|
||||
mCaches.textureState().bindTexture(renderTarget, id);
|
||||
}
|
||||
|
||||
if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
|
||||
@@ -77,7 +103,7 @@ void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool for
|
||||
}
|
||||
|
||||
void Texture::deleteTexture() const {
|
||||
mCaches.deleteTexture(id);
|
||||
mCaches.textureState().deleteTexture(id);
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
|
||||
@@ -296,7 +296,7 @@ void TextureCache::generateTexture(const SkBitmap* bitmap, Texture* texture, boo
|
||||
texture->width = bitmap->width();
|
||||
texture->height = bitmap->height();
|
||||
|
||||
Caches::getInstance().bindTexture(texture->id);
|
||||
Caches::getInstance().textureState().bindTexture(texture->id);
|
||||
|
||||
switch (bitmap->colorType()) {
|
||||
case kAlpha_8_SkColorType:
|
||||
|
||||
@@ -157,7 +157,7 @@ void CacheTexture::releaseTexture() {
|
||||
mTexture = nullptr;
|
||||
}
|
||||
if (mTextureId) {
|
||||
mCaches.deleteTexture(mTextureId);
|
||||
mCaches.textureState().deleteTexture(mTextureId);
|
||||
mTextureId = 0;
|
||||
}
|
||||
mDirty = false;
|
||||
@@ -169,7 +169,7 @@ void CacheTexture::setLinearFiltering(bool linearFiltering, bool bind) {
|
||||
mLinearFiltering = linearFiltering;
|
||||
|
||||
const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
|
||||
if (bind) mCaches.bindTexture(getTextureId());
|
||||
if (bind) mCaches.textureState().bindTexture(getTextureId());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||
}
|
||||
@@ -189,7 +189,7 @@ void CacheTexture::allocateTexture() {
|
||||
if (!mTextureId) {
|
||||
glGenTextures(1, &mTextureId);
|
||||
|
||||
mCaches.bindTexture(mTextureId);
|
||||
mCaches.textureState().bindTexture(mTextureId);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
// Initialize texture dimensions
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0,
|
||||
|
||||
121
libs/hwui/renderstate/Blend.cpp
Normal file
121
libs/hwui/renderstate/Blend.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include <renderstate/Blend.h>
|
||||
#include "Program.h"
|
||||
|
||||
#include "ShadowTessellator.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
/**
|
||||
* Structure mapping Skia xfermodes to OpenGL blending factors.
|
||||
*/
|
||||
struct Blender {
|
||||
SkXfermode::Mode mode;
|
||||
GLenum src;
|
||||
GLenum dst;
|
||||
};
|
||||
|
||||
// In this array, the index of each Blender equals the value of the first
|
||||
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
|
||||
const Blender kBlends[] = {
|
||||
{ SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO },
|
||||
{ SkXfermode::kDst_Mode, GL_ZERO, GL_ONE },
|
||||
{ SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
|
||||
{ SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
|
||||
{ SkXfermode::kModulate_Mode, GL_ZERO, GL_SRC_COLOR },
|
||||
{ SkXfermode::kScreen_Mode, GL_ONE, GL_ONE_MINUS_SRC_COLOR }
|
||||
};
|
||||
|
||||
// This array contains the swapped version of each SkXfermode. For instance
|
||||
// this array's SrcOver blending mode is actually DstOver. You can refer to
|
||||
// createLayer() for more information on the purpose of this array.
|
||||
const Blender kBlendsSwap[] = {
|
||||
{ SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE },
|
||||
{ SkXfermode::kDst_Mode, GL_ONE, GL_ZERO },
|
||||
{ SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE },
|
||||
{ SkXfermode::kDstOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kSrcIn_Mode, GL_ZERO, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kDstIn_Mode, GL_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kSrcOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kDstOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO },
|
||||
{ SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
|
||||
{ SkXfermode::kDstATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
|
||||
{ SkXfermode::kPlus_Mode, GL_ONE, GL_ONE },
|
||||
{ SkXfermode::kModulate_Mode, GL_DST_COLOR, GL_ZERO },
|
||||
{ SkXfermode::kScreen_Mode, GL_ONE_MINUS_DST_COLOR, GL_ONE }
|
||||
};
|
||||
|
||||
Blend::Blend()
|
||||
: mEnabled(false)
|
||||
, mSrcMode(GL_ZERO)
|
||||
, mDstMode(GL_ZERO) {
|
||||
// gl blending off by default
|
||||
}
|
||||
|
||||
void Blend::enable(SkXfermode::Mode mode, bool swapSrcDst) {
|
||||
// enable
|
||||
if (!mEnabled) {
|
||||
glEnable(GL_BLEND);
|
||||
mEnabled = true;
|
||||
}
|
||||
|
||||
// select blend mode
|
||||
GLenum sourceMode = swapSrcDst ? kBlendsSwap[mode].src : kBlends[mode].src;
|
||||
GLenum destMode = swapSrcDst ? kBlendsSwap[mode].dst : kBlends[mode].dst;
|
||||
|
||||
if (sourceMode != mSrcMode || destMode != mSrcMode) {
|
||||
glBlendFunc(sourceMode, destMode);
|
||||
mSrcMode = sourceMode;
|
||||
mDstMode = destMode;
|
||||
}
|
||||
}
|
||||
|
||||
void Blend::disable() {
|
||||
if (mEnabled) {
|
||||
glDisable(GL_BLEND);
|
||||
mEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Blend::invalidate() {
|
||||
syncEnabled();
|
||||
mSrcMode = mDstMode = GL_ZERO;
|
||||
}
|
||||
|
||||
void Blend::syncEnabled() {
|
||||
if (mEnabled) {
|
||||
glEnable(GL_BLEND);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
46
libs/hwui/renderstate/Blend.h
Normal file
46
libs/hwui/renderstate/Blend.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef RENDERSTATE_BLEND_H
|
||||
#define RENDERSTATE_BLEND_H
|
||||
|
||||
#include "Vertex.h"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#include <SkXfermode.h>
|
||||
#include <memory>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class Blend {
|
||||
friend class RenderState;
|
||||
public:
|
||||
void enable(SkXfermode::Mode mode, bool swapSrcDst);
|
||||
void disable();
|
||||
void syncEnabled();
|
||||
private:
|
||||
Blend();
|
||||
void invalidate();
|
||||
bool mEnabled;
|
||||
GLenum mSrcMode;
|
||||
GLenum mDstMode;
|
||||
};
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
#endif // RENDERSTATE_BLEND_H
|
||||
@@ -23,10 +23,6 @@ namespace uirenderer {
|
||||
|
||||
RenderState::RenderState(renderthread::RenderThread& thread)
|
||||
: mRenderThread(thread)
|
||||
, mCaches(nullptr)
|
||||
, mMeshState(nullptr)
|
||||
, mScissor(nullptr)
|
||||
, mStencil(nullptr)
|
||||
, mViewportWidth(0)
|
||||
, mViewportHeight(0)
|
||||
, mFramebuffer(0) {
|
||||
@@ -34,13 +30,14 @@ RenderState::RenderState(renderthread::RenderThread& thread)
|
||||
}
|
||||
|
||||
RenderState::~RenderState() {
|
||||
LOG_ALWAYS_FATAL_IF(mMeshState || mScissor || mStencil,
|
||||
LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
|
||||
"State object lifecycle not managed correctly");
|
||||
}
|
||||
|
||||
void RenderState::onGLContextCreated() {
|
||||
LOG_ALWAYS_FATAL_IF(mMeshState || mScissor || mStencil,
|
||||
LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil,
|
||||
"State object lifecycle not managed correctly");
|
||||
mBlend = new Blend();
|
||||
mMeshState = new MeshState();
|
||||
mScissor = new Scissor();
|
||||
mStencil = new Stencil();
|
||||
@@ -92,6 +89,10 @@ void RenderState::onGLContextDestroyed() {
|
||||
std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
|
||||
mAssetAtlas.terminate();
|
||||
|
||||
mCaches->terminate();
|
||||
|
||||
delete mBlend;
|
||||
mBlend = nullptr;
|
||||
delete mMeshState;
|
||||
mMeshState = nullptr;
|
||||
delete mScissor;
|
||||
@@ -132,7 +133,7 @@ void RenderState::interruptForFunctorInvoke() {
|
||||
mCaches->currentProgram = nullptr;
|
||||
}
|
||||
}
|
||||
mCaches->resetActiveTexture();
|
||||
mCaches->textureState().resetActiveTexture();
|
||||
meshState().unbindMeshBuffer();
|
||||
meshState().unbindIndicesBuffer();
|
||||
meshState().resetVertexPointers();
|
||||
@@ -148,14 +149,10 @@ void RenderState::resumeFromFunctorInvoke() {
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
scissor().invalidate();
|
||||
blend().invalidate();
|
||||
|
||||
mCaches->activeTexture(0);
|
||||
mCaches->resetBoundTextures();
|
||||
|
||||
mCaches->blend = true;
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(mCaches->lastSrcMode, mCaches->lastDstMode);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
mCaches->textureState().activateTexture(0);
|
||||
mCaches->textureState().resetBoundTextures();
|
||||
}
|
||||
|
||||
void RenderState::debugOverdraw(bool enable, bool clear) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include <private/hwui/DrawGlInfo.h>
|
||||
|
||||
#include <renderstate/Blend.h>
|
||||
#include "AssetAtlas.h"
|
||||
#include "Caches.h"
|
||||
#include "renderstate/MeshState.h"
|
||||
@@ -84,6 +84,7 @@ public:
|
||||
void postDecStrong(VirtualLightRefBase* object);
|
||||
|
||||
AssetAtlas& assetAtlas() { return mAssetAtlas; }
|
||||
Blend& blend() { return *mBlend; }
|
||||
MeshState& meshState() { return *mMeshState; }
|
||||
Scissor& scissor() { return *mScissor; }
|
||||
Stencil& stencil() { return *mStencil; }
|
||||
@@ -100,11 +101,12 @@ private:
|
||||
|
||||
|
||||
renderthread::RenderThread& mRenderThread;
|
||||
Caches* mCaches;
|
||||
Caches* mCaches = nullptr;
|
||||
|
||||
MeshState* mMeshState;
|
||||
Scissor* mScissor;
|
||||
Stencil* mStencil;
|
||||
Blend* mBlend = nullptr;
|
||||
MeshState* mMeshState = nullptr;
|
||||
Scissor* mScissor = nullptr;
|
||||
Stencil* mStencil = nullptr;
|
||||
|
||||
AssetAtlas mAssetAtlas;
|
||||
std::set<Layer*> mActiveLayers;
|
||||
|
||||
103
libs/hwui/renderstate/TextureState.cpp
Normal file
103
libs/hwui/renderstate/TextureState.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include <renderstate/TextureState.h>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
// Must define as many texture units as specified by kTextureUnitsCount
|
||||
const GLenum kTextureUnits[] = {
|
||||
GL_TEXTURE0,
|
||||
GL_TEXTURE1,
|
||||
GL_TEXTURE2
|
||||
};
|
||||
|
||||
TextureState::TextureState()
|
||||
: mTextureUnit(0) {
|
||||
glActiveTexture(kTextureUnits[0]);
|
||||
resetBoundTextures();
|
||||
|
||||
GLint maxTextureUnits;
|
||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
|
||||
LOG_ALWAYS_FATAL_IF(maxTextureUnits < kTextureUnitsCount,
|
||||
"At least %d texture units are required!", kTextureUnitsCount);
|
||||
}
|
||||
|
||||
void TextureState::activateTexture(GLuint textureUnit) {
|
||||
if (mTextureUnit != textureUnit) {
|
||||
glActiveTexture(kTextureUnits[textureUnit]);
|
||||
mTextureUnit = textureUnit;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureState::resetActiveTexture() {
|
||||
mTextureUnit = -1;
|
||||
}
|
||||
|
||||
void TextureState::bindTexture(GLuint texture) {
|
||||
if (mBoundTextures[mTextureUnit] != texture) {
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
mBoundTextures[mTextureUnit] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureState::bindTexture(GLenum target, GLuint texture) {
|
||||
if (target == GL_TEXTURE_2D) {
|
||||
bindTexture(texture);
|
||||
} else {
|
||||
// GLConsumer directly calls glBindTexture() with
|
||||
// target=GL_TEXTURE_EXTERNAL_OES, don't cache this target
|
||||
// since the cached state could be stale
|
||||
glBindTexture(target, texture);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureState::deleteTexture(GLuint texture) {
|
||||
// When glDeleteTextures() is called on a currently bound texture,
|
||||
// OpenGL ES specifies that the texture is then considered unbound
|
||||
// Consider the following series of calls:
|
||||
//
|
||||
// glGenTextures -> creates texture name 2
|
||||
// glBindTexture(2)
|
||||
// glDeleteTextures(2) -> 2 is now unbound
|
||||
// glGenTextures -> can return 2 again
|
||||
//
|
||||
// If we don't call glBindTexture(2) after the second glGenTextures
|
||||
// call, any texture operation will be performed on the default
|
||||
// texture (name=0)
|
||||
|
||||
unbindTexture(texture);
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
|
||||
void TextureState::resetBoundTextures() {
|
||||
for (int i = 0; i < kTextureUnitsCount; i++) {
|
||||
mBoundTextures[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureState::unbindTexture(GLuint texture) {
|
||||
for (int i = 0; i < kTextureUnitsCount; i++) {
|
||||
if (mBoundTextures[i] == texture) {
|
||||
mBoundTextures[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
88
libs/hwui/renderstate/TextureState.h
Normal file
88
libs/hwui/renderstate/TextureState.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef RENDERSTATE_TEXTURESTATE_H
|
||||
#define RENDERSTATE_TEXTURESTATE_H
|
||||
|
||||
#include "Vertex.h"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#include <SkXfermode.h>
|
||||
#include <memory>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class TextureState {
|
||||
friend class Caches; // TODO: move to RenderState
|
||||
public:
|
||||
/**
|
||||
* Activate the specified texture unit. The texture unit must
|
||||
* be specified using an integer number (0 for GL_TEXTURE0 etc.)
|
||||
*/
|
||||
void activateTexture(GLuint textureUnit);
|
||||
|
||||
/**
|
||||
* Invalidate the cached value of the active texture unit.
|
||||
*/
|
||||
void resetActiveTexture();
|
||||
|
||||
/**
|
||||
* Binds the specified texture as a GL_TEXTURE_2D texture.
|
||||
* All texture bindings must be performed with this method or
|
||||
* bindTexture(GLenum, GLuint).
|
||||
*/
|
||||
void bindTexture(GLuint texture);
|
||||
|
||||
/**
|
||||
* Binds the specified texture with the specified render target.
|
||||
* All texture bindings must be performed with this method or
|
||||
* bindTexture(GLuint).
|
||||
*/
|
||||
void bindTexture(GLenum target, GLuint texture);
|
||||
|
||||
/**
|
||||
* Deletes the specified texture and clears it from the cache
|
||||
* of bound textures.
|
||||
* All textures must be deleted using this method.
|
||||
*/
|
||||
void deleteTexture(GLuint texture);
|
||||
|
||||
/**
|
||||
* Signals that the cache of bound textures should be cleared.
|
||||
* Other users of the context may have altered which textures are bound.
|
||||
*/
|
||||
void resetBoundTextures();
|
||||
|
||||
/**
|
||||
* Clear the cache of bound textures.
|
||||
*/
|
||||
void unbindTexture(GLuint texture);
|
||||
private:
|
||||
// total number of texture units available for use
|
||||
static const int kTextureUnitsCount = 3;
|
||||
|
||||
TextureState();
|
||||
GLuint mTextureUnit;
|
||||
|
||||
// Caches texture bindings for the GL_TEXTURE_2D target
|
||||
GLuint mBoundTextures[kTextureUnitsCount];
|
||||
};
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
#endif // RENDERSTATE_BLEND_H
|
||||
@@ -214,9 +214,6 @@ void EglManager::destroy() {
|
||||
if (mEglDisplay == EGL_NO_DISPLAY) return;
|
||||
|
||||
usePBufferSurface();
|
||||
if (Caches::hasInstance()) {
|
||||
Caches::getInstance().terminate();
|
||||
}
|
||||
|
||||
mRenderThread.renderState().onGLContextDestroyed();
|
||||
eglDestroyContext(mEglDisplay, mEglContext);
|
||||
|
||||
Reference in New Issue
Block a user