Merge "Add implementation for drawBitmap()."
This commit is contained in:
@@ -54,10 +54,10 @@ static const GLsizei gDrawColorVertexCount = 4;
|
||||
// This array is never used directly but used as a memcpy source in the
|
||||
// OpenGLRenderer constructor
|
||||
static const TextureVertex gDrawTextureVertices[] = {
|
||||
FV(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
FV(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
FV(0.0f, 1.0f, 0.0f, 0.0f),
|
||||
FV(1.0f, 1.0f, 1.0f, 0.0f)
|
||||
FV(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
FV(1.0f, 0.0f, 1.0f, 0.0f),
|
||||
FV(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
FV(1.0f, 1.0f, 1.0f, 1.0f)
|
||||
};
|
||||
static const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
|
||||
static const GLsizei gDrawTextureVertexCount = 4;
|
||||
@@ -208,7 +208,7 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
|
||||
resetDrawTextureTexCoords(u1, v1, u2, v1);
|
||||
|
||||
drawTextureRect(layer.left, layer.top, layer.right, layer.bottom,
|
||||
current->texture, current->alpha, current->mode, true);
|
||||
current->texture, current->alpha, current->mode, true, true);
|
||||
|
||||
resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
|
||||
|
||||
@@ -378,8 +378,33 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)
|
||||
// Drawing
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
|
||||
LOGD("Drawing bitmap!");
|
||||
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
|
||||
Texture* texture = mTextureCache.get(bitmap);
|
||||
|
||||
SkXfermode::Mode mode;
|
||||
int alpha;
|
||||
|
||||
if (paint) {
|
||||
const bool isMode = SkXfermode::IsMode(paint->getXfermode(), &mode);
|
||||
if (!isMode) {
|
||||
// Assume SRC_OVER
|
||||
mode = SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
|
||||
// Skia draws using the color's alpha channel if < 255
|
||||
// Otherwise, it uses the paint's alpha
|
||||
int color = paint->getColor();
|
||||
alpha = (color >> 24) & 0xFF;
|
||||
if (alpha == 255) {
|
||||
alpha = paint->getAlpha();
|
||||
}
|
||||
} else {
|
||||
mode = SkXfermode::kSrcOver_Mode;
|
||||
alpha = 255;
|
||||
}
|
||||
|
||||
drawTextureRect(left, top, left + texture->width, top + texture->height, texture->id,
|
||||
alpha / 255.0f, mode, texture->blend, true);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
|
||||
@@ -443,23 +468,26 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
|
||||
GLuint texture, float alpha, SkXfermode::Mode mode, bool isPremultiplied) {
|
||||
GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied) {
|
||||
mModelView.loadTranslate(left, top, 0.0f);
|
||||
mModelView.scale(right - left, bottom - top, 1.0f);
|
||||
|
||||
mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);
|
||||
|
||||
GLenum sourceMode = gBlends[mode].src;
|
||||
if (!isPremultiplied && sourceMode == GL_ONE) {
|
||||
sourceMode = GL_SRC_ALPHA;
|
||||
if (blend || alpha < 1.0f || mode != SkXfermode::kSrcOver_Mode) {
|
||||
GLenum sourceMode = gBlends[mode].src;
|
||||
if (!isPremultiplied && sourceMode == GL_ONE) {
|
||||
sourceMode = GL_SRC_ALPHA;
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(sourceMode, gBlends[mode].dst);
|
||||
}
|
||||
|
||||
// TODO: Try to disable blending when the texture is opaque and alpha == 1.0f
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(sourceMode, gBlends[mode].dst);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// TODO handle tiling and filtering here
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(mDrawTextureShader->sampler, 0);
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
bool quickReject(float left, float top, float right, float bottom);
|
||||
bool clipRect(float left, float top, float right, float bottom);
|
||||
|
||||
void drawBitmap(const SkBitmap* bitmap, float left, float top, const SkPaint* paint);
|
||||
void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
|
||||
void drawColor(int color, SkXfermode::Mode mode);
|
||||
void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
|
||||
|
||||
@@ -183,10 +183,11 @@ private:
|
||||
* @param texture The texture name to map onto the rectangle
|
||||
* @param alpha An additional translucency parameter, between 0.0f and 1.0f
|
||||
* @param mode The blending mode
|
||||
* @param blend True if the texture contains an alpha channel
|
||||
* @param isPremultiplied Indicates whether the texture has premultiplied alpha
|
||||
*/
|
||||
void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
|
||||
float alpha, SkXfermode::Mode mode, bool isPremultiplied = false);
|
||||
float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied = false);
|
||||
|
||||
/**
|
||||
* Resets the texture coordinates stored in mDrawTextureVertices. Setting the values
|
||||
|
||||
@@ -41,7 +41,7 @@ Texture* TextureCache::get(SkBitmap* bitmap) {
|
||||
Texture* texture = mCache.get(bitmap);
|
||||
if (!texture) {
|
||||
texture = new Texture;
|
||||
generateTexture(bitmap, texture);
|
||||
generateTexture(bitmap, texture, false);
|
||||
mCache.put(bitmap, texture);
|
||||
} else if (bitmap->getGenerationID() != texture->generation) {
|
||||
generateTexture(bitmap, texture, true);
|
||||
@@ -58,7 +58,14 @@ void TextureCache::clear() {
|
||||
}
|
||||
|
||||
void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) {
|
||||
SkAutoLockPixels alp(*bitmap);
|
||||
if (!bitmap->readyToDraw()) {
|
||||
LOGE("Cannot generate texture from bitmap");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!regenerate) {
|
||||
texture->generation = bitmap->getGenerationID();
|
||||
texture->width = bitmap->width();
|
||||
texture->height = bitmap->height();
|
||||
|
||||
@@ -66,25 +73,28 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
|
||||
|
||||
switch (bitmap->getConfig()) {
|
||||
case SkBitmap::kRGB_565_Config:
|
||||
texture->blend = false;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->rowBytesAsPixels(), texture->height, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
|
||||
break;
|
||||
case SkBitmap::kARGB_8888_Config:
|
||||
texture->blend = true;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
switch (bitmap->getConfig()) {
|
||||
case SkBitmap::kRGB_565_Config:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, texture->width, texture->height,
|
||||
0, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
|
||||
break;
|
||||
case SkBitmap::kARGB_8888_Config:
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->width, texture->height,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<activity
|
||||
android:name="LayersActivity"
|
||||
android:label="_Layers"
|
||||
android:theme="@android:style/Theme.Translucent">
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
@@ -43,7 +43,7 @@
|
||||
<activity
|
||||
android:name="XfermodeActivity"
|
||||
android:label="_Xfermodes"
|
||||
android:theme="@android:style/Theme.Translucent">
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
@@ -53,7 +53,7 @@
|
||||
<activity
|
||||
android:name="BitmapsActivity"
|
||||
android:label="_Bitmaps"
|
||||
android:theme="@android:style/Theme.Translucent">
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
@@ -26,13 +26,24 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public class BitmapsActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(new BitmapsView(this));
|
||||
final BitmapsView view = new BitmapsView(this);
|
||||
setContentView(view);
|
||||
|
||||
ScaleAnimation a = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f,
|
||||
ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
|
||||
ScaleAnimation.RELATIVE_TO_SELF,0.5f);
|
||||
a.setDuration(2000);
|
||||
a.setRepeatCount(Animation.INFINITE);
|
||||
a.setRepeatMode(Animation.REVERSE);
|
||||
view.startAnimation(a);
|
||||
}
|
||||
|
||||
static class BitmapsView extends View {
|
||||
|
||||
Reference in New Issue
Block a user