Merge changes I94b1c31c,Ib0b16c87

* changes:
  Add target to texture
  Use Bitmap in Texture.upload
This commit is contained in:
Sergei Vasilinetc
2016-10-28 01:30:56 +00:00
committed by Android (Google) Code Review
15 changed files with 138 additions and 144 deletions

View File

@@ -119,7 +119,6 @@ public:
struct TextureData {
Texture* texture;
GLenum target;
GLenum filter;
GLenum clamp;
Matrix4* textureTransform;

View File

@@ -308,8 +308,7 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture,
GLenum filter = (textureFillFlags & TextureFillFlags::ForceFilter)
? GL_LINEAR : PaintUtils::getFilter(paint);
mOutGlop->fill.texture = { &texture,
GL_TEXTURE_2D, filter, GL_CLAMP_TO_EDGE, nullptr };
mOutGlop->fill.texture = { &texture, filter, GL_CLAMP_TO_EDGE, nullptr };
if (paint) {
int color = paint->getColor();
@@ -352,10 +351,10 @@ GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale, b
if (CC_LIKELY(!shadowInterp)) {
mOutGlop->fill.texture = {
nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
} else {
mOutGlop->fill.texture = {
mCaches.textureState().getShadowLutTexture(), GL_TEXTURE_2D,
mCaches.textureState().getShadowLutTexture(),
GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
}
@@ -373,7 +372,7 @@ GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
//specify invalid filter/clamp, since these are always static for PathTextures
mOutGlop->fill.texture = { &texture, GL_TEXTURE_2D, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
setFill(paint.getColor(), alphaScale,
paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap,
@@ -390,7 +389,7 @@ GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
//specify invalid filter/clamp, since these are always static for ShadowTextures
mOutGlop->fill.texture = { &texture, GL_TEXTURE_2D, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
const int ALPHA_BITMASK = SK_ColorBLACK;
const int COLOR_BITMASK = ~ALPHA_BITMASK;
@@ -412,7 +411,7 @@ GlopBuilder& GlopBuilder::setFillBlack() {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kSrcOver, Blend::ModeOrderSwap::NoSwap,
nullptr, nullptr);
return *this;
@@ -422,7 +421,7 @@ GlopBuilder& GlopBuilder::setFillClear() {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
setFill(SK_ColorBLACK, 1.0f, SkBlendMode::kClear, Blend::ModeOrderSwap::NoSwap,
nullptr, nullptr);
return *this;
@@ -433,8 +432,7 @@ GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* co
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
mOutGlop->fill.texture = { &texture,
GL_TEXTURE_2D, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };
mOutGlop->fill.texture = { &texture, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };
setFill(SK_ColorWHITE, alpha, mode, modeUsage, nullptr, colorFilter);
@@ -447,7 +445,7 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
mOutGlop->fill.texture = { &(layer.getTexture()),
layer.getRenderTarget(), GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };
GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };
setFill(SK_ColorWHITE, alpha, layer.getMode(), Blend::ModeOrderSwap::NoSwap,
nullptr, layer.getColorFilter());
@@ -461,9 +459,7 @@ GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& text
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
mOutGlop->fill.texture = { &texture,
GL_TEXTURE_EXTERNAL_OES, GL_LINEAR, GL_CLAMP_TO_EDGE,
&textureTransform };
mOutGlop->fill.texture = { &texture, GL_LINEAR, GL_CLAMP_TO_EDGE, &textureTransform };
setFill(SK_ColorWHITE, 1.0f, SkBlendMode::kSrc, Blend::ModeOrderSwap::NoSwap,
nullptr, nullptr);
@@ -603,7 +599,7 @@ void verify(const ProgramDescription& description, const Glop& glop) {
void GlopBuilder::build() {
REQUIRE_STAGES(kAllStages);
if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) {
if (mOutGlop->fill.texture.target == GL_TEXTURE_2D) {
if (mOutGlop->fill.texture.texture->target() == GL_TEXTURE_2D) {
mDescription.hasTexture = true;
} else {
mDescription.hasExternalTexture = true;
@@ -668,7 +664,8 @@ void GlopBuilder::dump(const Glop& glop) {
ALOGD(" program %p", fill.program);
if (fill.texture.texture) {
ALOGD(" texture %p, target %d, filter %d, clamp %d",
fill.texture.texture, fill.texture.target, fill.texture.filter, fill.texture.clamp);
fill.texture.texture, fill.texture.texture->target(),
fill.texture.filter, fill.texture.clamp);
if (fill.texture.textureTransform) {
fill.texture.textureTransform->dump("texture transform");
}

View File

@@ -72,9 +72,8 @@ public:
GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
float alpha, SkBlendMode mode, Blend::ModeOrderSwap modeUsage);
GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
// TODO: Texture should probably know and own its target.
// setFillLayer() forces it to GL_TEXTURE which isn't always correct.
// Similarly setFillLayer normally forces its own wrap & filter mode
// TODO: setFillLayer normally forces its own wrap & filter mode,
// which isn't always correct.
GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform);
GlopBuilder& setTransform(const Matrix4& canvas, const int transformFlags);

View File

@@ -41,7 +41,6 @@ Layer::Layer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight
// TODO: This is a violation of Android's typical ref counting, but it
// preserves the old inc/dec ref locations. This should be changed...
incStrong(nullptr);
renderTarget = GL_NONE; // see DeferredLayerUpdater::updateLayer()
texture.mWidth = layerWidth;
texture.mHeight = layerHeight;
renderState.registerLayer(this);
@@ -66,7 +65,7 @@ void Layer::setColorFilter(SkColorFilter* filter) {
void Layer::bindTexture() const {
if (texture.mId) {
caches.textureState().bindTexture(renderTarget, texture.mId);
caches.textureState().bindTexture(texture.target(), texture.mId);
}
}

View File

@@ -75,7 +75,8 @@ public:
}
void setSize(uint32_t width, uint32_t height) {
texture.updateSize(width, height, texture.internalFormat(), texture.format());
texture.updateSize(width, height, texture.internalFormat(), texture.format(),
texture.target());
}
inline void setBlend(bool blend) {
@@ -120,23 +121,23 @@ public:
}
inline GLenum getRenderTarget() const {
return renderTarget;
return texture.target();
}
inline void setRenderTarget(GLenum renderTarget) {
this->renderTarget = renderTarget;
texture.mTarget = renderTarget;
}
inline bool isRenderable() const {
return renderTarget != GL_NONE;
return texture.target() != GL_NONE;
}
void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
texture.setWrap(wrap, bindTexture, force, renderTarget);
texture.setWrap(wrap, bindTexture, force);
}
void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
texture.setFilter(filter, bindTexture, force, renderTarget);
texture.setFilter(filter, bindTexture, force);
}
inline SkColorFilter* getColorFilter() const {
@@ -185,11 +186,6 @@ private:
*/
Texture texture;
/**
* Indicates the render target.
*/
GLenum renderTarget = GL_TEXTURE_2D;
/**
* Color filter used to draw this layer. Optional.
*/

View File

@@ -138,11 +138,6 @@ static void computePathBounds(const SkPath* path, const SkPaint* paint, PathText
height = uint32_t(pathHeight + texture->offset * 2.0 + 0.5);
}
static void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
bitmap.allocPixels(SkImageInfo::MakeA8(width, height));
bitmap.eraseColor(0);
}
static void initPaint(SkPaint& paint) {
// Make sure the paint is opaque, color, alpha, filter, etc.
// will be applied later when compositing the alpha8 texture
@@ -154,7 +149,7 @@ static void initPaint(SkPaint& paint) {
paint.setBlendMode(SkBlendMode::kSrc);
}
static SkBitmap* drawPath(const SkPath* path, const SkPaint* paint, PathTexture* texture,
static sk_sp<Bitmap> drawPath(const SkPath* path, const SkPaint* paint, PathTexture* texture,
uint32_t maxTextureSize) {
uint32_t width, height;
computePathBounds(path, paint, texture, width, height);
@@ -164,13 +159,14 @@ static SkBitmap* drawPath(const SkPath* path, const SkPaint* paint, PathTexture*
return nullptr;
}
SkBitmap* bitmap = new SkBitmap();
initBitmap(*bitmap, width, height);
sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(width, height));
SkPaint pathPaint(*paint);
initPaint(pathPaint);
SkCanvas canvas(*bitmap);
SkBitmap skBitmap;
bitmap->getSkBitmap(&skBitmap);
skBitmap.eraseColor(0);
SkCanvas canvas(skBitmap);
canvas.translate(-texture->left + texture->offset, -texture->top + texture->offset);
canvas.drawPath(*path, pathPaint);
return bitmap;
@@ -227,7 +223,7 @@ void PathCache::removeTexture(PathTexture* texture) {
// If there is a pending task we must wait for it to return
// before attempting our cleanup
const sp<Task<SkBitmap*> >& task = texture->task();
const sp<PathTask>& task = texture->task();
if (task != nullptr) {
task->getResult();
texture->clearTask();
@@ -280,20 +276,20 @@ PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *p
ATRACE_NAME("Generate Path Texture");
PathTexture* texture = new PathTexture(Caches::getInstance(), path->getGenerationID());
std::unique_ptr<SkBitmap> bitmap(drawPath(path, paint, texture, mMaxTextureSize));
if (!bitmap.get()) {
sk_sp<Bitmap> bitmap(drawPath(path, paint, texture, mMaxTextureSize));
if (!bitmap) {
delete texture;
return nullptr;
}
purgeCache(bitmap->width(), bitmap->height());
generateTexture(entry, bitmap.get(), texture);
generateTexture(entry, *bitmap, texture);
return texture;
}
void PathCache::generateTexture(const PathDescription& entry, SkBitmap* bitmap,
void PathCache::generateTexture(const PathDescription& entry, Bitmap& bitmap,
PathTexture* texture, bool addToCache) {
generateTexture(*bitmap, texture);
generateTexture(bitmap, texture);
// Note here that we upload to a texture even if it's bigger than mMaxSize.
// Such an entry in mCache will only be temporary, since it will be evicted
@@ -314,7 +310,7 @@ void PathCache::clear() {
mCache.clear();
}
void PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) {
void PathCache::generateTexture(Bitmap& bitmap, Texture* texture) {
ATRACE_NAME("Upload Path Texture");
texture->upload(bitmap);
texture->setFilter(GL_LINEAR);
@@ -325,10 +321,10 @@ void PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) {
///////////////////////////////////////////////////////////////////////////////
PathCache::PathProcessor::PathProcessor(Caches& caches):
TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) {
TaskProcessor<sk_sp<Bitmap> >(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) {
}
void PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) {
void PathCache::PathProcessor::onProcess(const sp<Task<sk_sp<Bitmap> > >& task) {
PathTask* t = static_cast<PathTask*>(task.get());
ATRACE_NAME("pathPrecache");
@@ -377,13 +373,13 @@ PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) {
} else {
// A bitmap is attached to the texture, this means we need to
// upload it as a GL texture
const sp<Task<SkBitmap*> >& task = texture->task();
const sp<PathTask>& task = texture->task();
if (task != nullptr) {
// But we must first wait for the worker thread to be done
// producing the bitmap, so let's wait
SkBitmap* bitmap = task->getResult();
sk_sp<Bitmap> bitmap = task->getResult();
if (bitmap) {
generateTexture(entry, bitmap, texture, false);
generateTexture(entry, *bitmap, texture, false);
texture->clearTask();
} else {
texture->clearTask();

View File

@@ -19,6 +19,7 @@
#include "Debug.h"
#include "Texture.h"
#include "hwui/Bitmap.h"
#include "thread/Task.h"
#include "thread/TaskProcessor.h"
#include "utils/Macros.h"
@@ -32,7 +33,6 @@
#include <vector>
class SkBitmap;
class SkCanvas;
class SkPaint;
struct SkRect;
@@ -41,7 +41,6 @@ namespace android {
namespace uirenderer {
class Caches;
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
@@ -57,6 +56,21 @@ class Caches;
// Classes
///////////////////////////////////////////////////////////////////////////////
struct PathTexture;
class PathTask: public Task<sk_sp<Bitmap>> {
public:
PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture):
path(*path), paint(*paint), texture(texture) {
}
// copied, since input path not guaranteed to survive for duration of task
const SkPath path;
// copied, since input paint may not be immutable
const SkPaint paint;
PathTexture* texture;
};
/**
* Alpha texture used to represent a path.
*/
@@ -83,11 +97,11 @@ struct PathTexture: public Texture {
*/
float offset = 0;
sp<Task<SkBitmap*> > task() const {
sp<PathTask> task() const {
return mTask;
}
void setTask(const sp<Task<SkBitmap*> >& task) {
void setTask(const sp<PathTask>& task) {
mTask = task;
}
@@ -98,7 +112,7 @@ struct PathTexture: public Texture {
}
private:
sp<Task<SkBitmap*> > mTask;
sp<PathTask> mTask;
}; // struct PathTexture
enum class ShapeType {
@@ -222,13 +236,12 @@ public:
private:
PathTexture* addTexture(const PathDescription& entry,
const SkPath *path, const SkPaint* paint);
PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap);
/**
* Generates the texture from a bitmap into the specified texture structure.
*/
void generateTexture(SkBitmap& bitmap, Texture* texture);
void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture,
void generateTexture(Bitmap& bitmap, Texture* texture);
void generateTexture(const PathDescription& entry, Bitmap& bitmap, PathTexture* texture,
bool addToCache = true);
PathTexture* get(const PathDescription& entry) {
@@ -245,30 +258,13 @@ private:
void init();
class PathTask: public Task<SkBitmap*> {
public:
PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture):
path(*path), paint(*paint), texture(texture) {
}
~PathTask() {
delete future()->get();
}
// copied, since input path not guaranteed to survive for duration of task
const SkPath path;
// copied, since input paint may not be immutable
const SkPaint paint;
PathTexture* texture;
};
class PathProcessor: public TaskProcessor<SkBitmap*> {
class PathProcessor: public TaskProcessor<sk_sp<Bitmap> > {
public:
explicit PathProcessor(Caches& caches);
~PathProcessor() { }
virtual void onProcess(const sp<Task<SkBitmap*> >& task) override;
virtual void onProcess(const sp<Task<sk_sp<Bitmap> > >& task) override;
private:
uint32_t mMaxTextureSize;

View File

@@ -196,8 +196,8 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
}
Texture sourceTexture(caches);
sourceTexture.wrap(sourceTexId,
sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0, 0 /* total lie */);
sourceTexture.wrap(sourceTexId, sourceBuffer->getWidth(),
sourceBuffer->getHeight(), 0, 0 /* total lie */, GL_TEXTURE_EXTERNAL_OES);
CopyResult copyResult = copyTextureInto(caches, renderThread.renderState(),
sourceTexture, texTransform, srcRect, bitmap);

View File

@@ -666,7 +666,6 @@ void RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
SkBitmap bitmap;
SkShader::TileMode xy[2];
if (shader->isABitmap(&bitmap, nullptr, xy)) {
// TODO: create hwui-owned BitmapShader.
Bitmap* hwuiBitmap = static_cast<Bitmap*>(bitmap.pixelRef());
refBitmap(*hwuiBitmap);
return;

View File

@@ -48,37 +48,34 @@ static int bytesPerPixel(GLint glFormat) {
}
}
void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force,
GLenum renderTarget) {
void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force) {
if (force || wrapS != mWrapS || wrapT != mWrapT) {
mWrapS = wrapS;
mWrapT = wrapT;
if (bindTexture) {
mCaches.textureState().bindTexture(renderTarget, mId);
mCaches.textureState().bindTexture(mTarget, mId);
}
glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
glTexParameteri(mTarget, GL_TEXTURE_WRAP_S, wrapS);
glTexParameteri(mTarget, GL_TEXTURE_WRAP_T, wrapT);
}
}
void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool force,
GLenum renderTarget) {
void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool force) {
if (force || min != mMinFilter || mag != mMagFilter) {
mMinFilter = min;
mMagFilter = mag;
if (bindTexture) {
mCaches.textureState().bindTexture(renderTarget, mId);
mCaches.textureState().bindTexture(mTarget, mId);
}
if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, min);
glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, mag);
}
}
@@ -87,15 +84,20 @@ void Texture::deleteTexture() {
mId = 0;
}
bool Texture::updateSize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
if (mWidth == width && mHeight == height &&
mFormat == format && mInternalFormat == internalFormat) {
bool Texture::updateSize(uint32_t width, uint32_t height, GLint internalFormat,
GLint format, GLenum target) {
if (mWidth == width
&& mHeight == height
&& mFormat == format
&& mInternalFormat == internalFormat
&& mTarget == target) {
return false;
}
mWidth = width;
mHeight = height;
mFormat = format;
mInternalFormat = internalFormat;
mTarget = target;
notifySizeChanged(mWidth * mHeight * bytesPerPixel(internalFormat));
return true;
}
@@ -110,7 +112,7 @@ void Texture::resetCachedParams() {
void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height,
GLenum format, GLenum type, const void* pixels) {
GL_CHECKPOINT(MODERATE);
bool needsAlloc = updateSize(width, height, internalFormat, format);
bool needsAlloc = updateSize(width, height, internalFormat, format, GL_TEXTURE_2D);
if (!mId) {
glGenTextures(1, &mId);
needsAlloc = true;
@@ -171,12 +173,6 @@ static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GL
}
}
static void uploadSkBitmapToTexture(const SkBitmap& bitmap,
bool resize, GLint internalFormat, GLenum format, GLenum type) {
uploadToTexture(resize, internalFormat, format, type, bitmap.rowBytesAsPixels(),
bitmap.bytesPerPixel(), bitmap.width(), bitmap.height(), bitmap.getPixels());
}
static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType) {
switch (colorType) {
@@ -218,9 +214,7 @@ static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorTy
}
}
void Texture::upload(const SkBitmap& bitmap) {
SkAutoLockPixels alp(bitmap);
void Texture::upload(Bitmap& bitmap) {
if (!bitmap.readyToDraw()) {
ALOGE("Cannot generate texture from bitmap");
return;
@@ -244,12 +238,12 @@ void Texture::upload(const SkBitmap& bitmap) {
}
sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
bool needSRGB = bitmap.colorSpace() == sRGB.get();
bool needSRGB = bitmap.info().colorSpace() == sRGB.get();
GLint internalFormat, format, type;
colorTypeToGlFormatAndType(mCaches, bitmap.colorType(), needSRGB, &internalFormat, &format, &type);
if (updateSize(bitmap.width(), bitmap.height(), internalFormat, format)) {
if (updateSize(bitmap.width(), bitmap.height(), internalFormat, format, GL_TEXTURE_2D)) {
needsAlloc = true;
}
@@ -264,15 +258,21 @@ void Texture::upload(const SkBitmap& bitmap) {
SkBitmap rgbaBitmap;
rgbaBitmap.allocPixels(SkImageInfo::MakeN32(
mWidth, mHeight, bitmap.alphaType(), hasSRGB ? sRGB : nullptr));
mWidth, mHeight, bitmap.info().alphaType(), hasSRGB ? sRGB : nullptr));
rgbaBitmap.eraseColor(0);
SkCanvas canvas(rgbaBitmap);
canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
SkBitmap skBitmap;
bitmap.getSkBitmap(&skBitmap);
canvas.drawBitmap(skBitmap, 0.0f, 0.0f, nullptr);
uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(),
rgbaBitmap.height(), rgbaBitmap.getPixels());
uploadSkBitmapToTexture(rgbaBitmap, needsAlloc, internalFormat, format, type);
} else {
uploadSkBitmapToTexture(bitmap, needsAlloc, internalFormat, format, type);
uploadToTexture(needsAlloc, internalFormat, format, type, bitmap.rowBytesAsPixels(),
bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(), bitmap.pixels());
}
if (canMipMap) {
@@ -288,12 +288,14 @@ void Texture::upload(const SkBitmap& bitmap) {
}
}
void Texture::wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
void Texture::wrap(GLuint id, uint32_t width, uint32_t height,
GLint internalFormat, GLint format, GLenum target) {
mId = id;
mWidth = width;
mHeight = height;
mFormat = format;
mInternalFormat = internalFormat;
mTarget = target;
// We're wrapping an existing texture, so don't double count this memory
notifySizeChanged(0);
}

View File

@@ -18,9 +18,9 @@
#define ANDROID_HWUI_TEXTURE_H
#include "GpuMemoryTracker.h"
#include "hwui/Bitmap.h"
#include <GLES2/gl2.h>
#include <SkBitmap.h>
namespace android {
namespace uirenderer {
@@ -41,21 +41,19 @@ public:
virtual ~Texture() { }
inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false,
GLenum renderTarget = GL_TEXTURE_2D) {
setWrapST(wrap, wrap, bindTexture, force, renderTarget);
inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
setWrapST(wrap, wrap, bindTexture, force);
}
virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
bool force = false, GLenum renderTarget = GL_TEXTURE_2D);
bool force = false);
inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false,
GLenum renderTarget = GL_TEXTURE_2D) {
setFilterMinMag(filter, filter, bindTexture, force, renderTarget);
inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
setFilterMinMag(filter, filter, bindTexture, force);
}
virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
bool force = false, GLenum renderTarget = GL_TEXTURE_2D);
bool force = false);
/**
* Convenience method to call glDeleteTextures() on this texture's id.
@@ -74,13 +72,13 @@ public:
}
/**
* Updates this Texture with the contents of the provided SkBitmap,
* Updates this Texture with the contents of the provided Bitmap,
* also setting the appropriate width, height, and format. It is not necessary
* to call resize() prior to this.
*
* Note this does not set the generation from the SkBitmap.
* Note this does not set the generation from the Bitmap.
*/
void upload(const SkBitmap& source);
void upload(Bitmap& source);
/**
* Basically glTexImage2D/glTexSubImage2D.
@@ -91,7 +89,8 @@ public:
/**
* Wraps an existing texture.
*/
void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format);
void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat,
GLint format, GLenum target);
GLuint id() const {
return mId;
@@ -113,6 +112,10 @@ public:
return mInternalFormat;
}
GLenum target() const {
return mTarget;
}
/**
* Generation of the backing bitmap,
*/
@@ -152,7 +155,8 @@ private:
friend class Layer;
// Returns true if the size changed, false if it was the same
bool updateSize(uint32_t width, uint32_t height, GLint internalFormat, GLint format);
bool updateSize(uint32_t width, uint32_t height, GLint internalFormat,
GLint format, GLenum target);
void resetCachedParams();
GLuint mId = 0;
@@ -160,6 +164,7 @@ private:
uint32_t mHeight = 0;
GLint mFormat = 0;
GLint mInternalFormat = 0;
GLenum mTarget = GL_NONE;
/* See GLES spec section 3.8.14
* "In the initial state, the value assigned to TEXTURE_MIN_FILTER is

View File

@@ -127,9 +127,7 @@ Texture* TextureCache::getCachedTexture(Bitmap* bitmap) {
texture = new Texture(Caches::getInstance());
texture->bitmapSize = size;
texture->generation = bitmap->getGenerationID();
SkBitmap skBitmap;
bitmap->getSkBitmap(&skBitmap);
texture->upload(skBitmap);
texture->upload(*bitmap);
mSize += size;
TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
@@ -142,9 +140,7 @@ Texture* TextureCache::getCachedTexture(Bitmap* bitmap) {
} else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
// Texture was in the cache but is dirty, re-upload
// TODO: Re-adjust the cache size if the bitmap's dimensions have changed
SkBitmap skBitmap;
bitmap->getSkBitmap(&skBitmap);
texture->upload(skBitmap);
texture->upload(*bitmap);
texture->generation = bitmap->getGenerationID();
}
@@ -174,9 +170,7 @@ Texture* TextureCache::get(Bitmap* bitmap) {
const uint32_t size = bitmap->rowBytes() * bitmap->height();
texture = new Texture(Caches::getInstance());
texture->bitmapSize = size;
SkBitmap skBitmap;
bitmap->getSkBitmap(&skBitmap);
texture->upload(skBitmap);
texture->upload(*bitmap);
texture->generation = bitmap->getGenerationID();
texture->cleanup = true;
}

View File

@@ -57,6 +57,11 @@ public:
// doing on a Bitmap type, not a SkPixelRef, so static
// dispatching will do what we want.
size_t rowBytes() const { return mRowBytes; }
int rowBytesAsPixels() const {
return mRowBytes >> info().shiftPerPixel();
}
void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
void reconfigure(const SkImageInfo& info);
void setAlphaType(SkAlphaType alphaType);
@@ -73,6 +78,9 @@ public:
SkColorType colorType() const { return info().colorType(); }
void getBounds(SkRect* bounds) const;
bool readyToDraw() const {
return this->colorType() != kIndex_8_SkColorType || mColorTable;
}
protected:
virtual bool onNewLockPixels(LockRec* rec) override;
virtual void onUnlockPixels() override { };

View File

@@ -278,12 +278,12 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) {
// texture always takes slot 0, shader samplers increment from there
mCaches->textureState().activateTexture(0);
mCaches->textureState().bindTexture(texture.target, texture.texture->id());
mCaches->textureState().bindTexture(texture.texture->target(), texture.texture->id());
if (texture.clamp != GL_INVALID_ENUM) {
texture.texture->setWrap(texture.clamp, false, false, texture.target);
texture.texture->setWrap(texture.clamp, false, false);
}
if (texture.filter != GL_INVALID_ENUM) {
texture.texture->setFilter(texture.filter, false, false, texture.target);
texture.texture->setFilter(texture.filter, false, false);
}
if (texture.textureTransform) {

View File

@@ -45,7 +45,11 @@ static void expectFillEq(Glop::Fill& expectedFill, Glop::Fill& builtFill) {
EXPECT_EQ(expectedFill.skiaShaderData.skiaShaderType, builtFill.skiaShaderData.skiaShaderType);
EXPECT_EQ(expectedFill.texture.clamp, builtFill.texture.clamp);
EXPECT_EQ(expectedFill.texture.filter, builtFill.texture.filter);
EXPECT_EQ(expectedFill.texture.target, builtFill.texture.target);
EXPECT_TRUE((expectedFill.texture.texture && builtFill.texture.texture)
|| (!expectedFill.texture.texture && !builtFill.texture.texture));
if (expectedFill.texture.texture) {
EXPECT_EQ(expectedFill.texture.texture->target(), builtFill.texture.texture->target());
}
EXPECT_EQ(expectedFill.texture.textureTransform, builtFill.texture.textureTransform);
}
@@ -108,7 +112,7 @@ static std::unique_ptr<Glop> blackUnitQuadGlop(RenderState& renderState) {
glop->fill.color.set(Color::Black);
glop->fill.skiaShaderData.skiaShaderType = kNone_SkiaShaderType;
glop->fill.filterMode = ProgramDescription::ColorFilterMode::None;
glop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
glop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
return glop;
}