Correct implementation of saveLayer().

Change-Id: I5375126636913e0a84f2d6bbd0ebe40d2e4f2763
This commit is contained in:
Romain Guy
2010-09-10 19:20:06 -07:00
parent d14f0dfd58
commit f607bdc167
37 changed files with 383 additions and 193 deletions

View File

@@ -16,9 +16,6 @@
package android.view;
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -49,8 +46,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.Config;
import android.util.EventLog;
import android.util.Log;
import android.util.Pool;
import android.util.Poolable;
@@ -67,6 +62,8 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.ScrollBarDrawable;
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -4022,12 +4019,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
public boolean dispatchKeyEvent(KeyEvent event) {
// If any attached key listener a first crack at the event.
//noinspection SimplifiableIfStatement
//noinspection SimplifiableIfStatement,deprecation
if (android.util.Config.LOGV) {
captureViewInfo("captureViewKeyEvent", this);
}
//noinspection SimplifiableIfStatement
if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
return true;
@@ -4059,6 +4057,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return false;
}
//noinspection SimplifiableIfStatement
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
@@ -4075,6 +4074,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @see #getFilterTouchesWhenObscured
*/
public boolean onFilterTouchEventForSecurity(MotionEvent event) {
//noinspection RedundantIfStatement
if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
&& (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
// Window is obscured, drop this touch.
@@ -7829,8 +7829,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
saveCount = canvas.getSaveCount();
int solidColor = getSolidColor();
// TODO: Temporarily disable fading edges with hardware acceleration
if (solidColor == 0 && !canvas.isHardwareAccelerated()) {
if (solidColor == 0) {
final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
if (drawTop) {
@@ -9577,6 +9576,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (mAttachInfo == null) {
return false;
}
//noinspection SimplifiableIfStatement
if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
&& !isHapticFeedbackEnabled()) {
return false;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 916 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -63,28 +63,19 @@ struct LayerSize {
*/
struct Layer {
/**
* Coordinates of the layer corresponding to this snapshot.
* Only set when the flag kFlagIsLayer is set.
* Coordinates of the layer.
*/
Rect layer;
/**
* Name of the texture used to render the layer.
* Only set when the flag kFlagIsLayer is set.
*/
GLuint texture;
/**
* Name of the FBO used to render the layer.
* Only set when the flag kFlagIsLayer is set.
*/
GLuint fbo;
/**
* Opacity of the layer.
* Only set when the flag kFlagIsLayer is set.
*/
float alpha;
int alpha;
/**
* Blending mode of the layer.
* Only set when the flag kFlagIsLayer is set.
*/
SkXfermode::Mode mode;
/**

View File

@@ -87,7 +87,6 @@ void LayerCache::deleteLayer(Layer* layer) {
if (layer) {
mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4;
glDeleteFramebuffers(1, &layer->fbo);
glDeleteTextures(1, &layer->texture);
delete layer;
}
@@ -99,7 +98,7 @@ void LayerCache::clear() {
mCache.setOnEntryRemovedListener(NULL);
}
Layer* LayerCache::get(LayerSize& size, GLuint previousFbo) {
Layer* LayerCache::get(LayerSize& size) {
Layer* layer = mCache.remove(size);
if (layer) {
LAYER_LOGD("Reusing layer");
@@ -111,10 +110,6 @@ Layer* LayerCache::get(LayerSize& size, GLuint previousFbo) {
layer = new Layer;
layer->blend = true;
// Generate the FBO and attach the texture
glGenFramebuffers(1, &layer->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
// Generate the texture in which the FBO will draw
glGenTextures(1, &layer->texture);
glBindTexture(GL_TEXTURE_2D, layer->texture);
@@ -128,23 +123,6 @@ Layer* LayerCache::get(LayerSize& size, GLuint previousFbo) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// Bind texture to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
layer->texture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
LOGE("Framebuffer incomplete (GL error code 0x%x)", status);
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
glDeleteFramebuffers(1, &layer->fbo);
glDeleteTextures(1, &layer->texture);
delete layer;
return NULL;
}
}
return layer;

View File

@@ -62,10 +62,8 @@ public:
* size of the cache goes down.
*
* @param size The dimensions of the desired layer
* @param previousFbo The name of the FBO to bind to if creating a new
* layer fails
*/
Layer* get(LayerSize& size, GLuint previousFbo);
Layer* get(LayerSize& size);
/**
* Adds the layer to the cache. The layer will not be added if there is
* not enough space available.

View File

@@ -80,6 +80,21 @@ static const Blender gBlends[] = {
{ SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }
};
static const Blender gBlendsSwap[] = {
{ SkXfermode::kClear_Mode, GL_ZERO, 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 }
};
static const GLenum gTextureUnits[] = {
GL_TEXTURE0,
GL_TEXTURE1,
@@ -122,8 +137,6 @@ void OpenGLRenderer::setViewport(int width, int height) {
mWidth = width;
mHeight = height;
mFirstSnapshot->height = height;
mFirstSnapshot->viewport.set(0, 0, width, height);
}
void OpenGLRenderer::prepare() {
@@ -155,14 +168,19 @@ void OpenGLRenderer::acquireContext() {
}
void OpenGLRenderer::releaseContext() {
glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight());
glViewport(0, 0, mWidth, mHeight);
glEnable(GL_SCISSOR_TEST);
setScissorFromClip();
glDisable(GL_DITHER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (mCaches.blend) {
glEnable(GL_BLEND);
glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
glBlendEquation(GL_FUNC_ADD);
} else {
glDisable(GL_BLEND);
}
@@ -202,17 +220,10 @@ int OpenGLRenderer::saveSnapshot(int flags) {
bool OpenGLRenderer::restoreSnapshot() {
bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer;
bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho;
sp<Snapshot> current = mSnapshot;
sp<Snapshot> previous = mSnapshot->previous;
if (restoreOrtho) {
Rect& r = previous->viewport;
glViewport(r.left, r.top, r.right, r.bottom);
mOrthoMatrix.load(current->orthoMatrix);
}
mSaveCount--;
mSnapshot = previous;
@@ -253,11 +264,7 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
mode = SkXfermode::kSrcOver_Mode;
}
if (alpha > 0 && !mSnapshot->invisible) {
createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags);
} else {
mSnapshot->invisible = true;
}
createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags);
return count;
}
@@ -278,49 +285,42 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
LAYER_LOGD("Requesting layer %fx%f", right - left, bottom - top);
LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
// Window coordinates of the layer
Rect bounds(left, top, right, bottom);
// TODO: Apply transformations and treat layers in screen coordinates
// mSnapshot->transform->mapRect(bounds);
mSnapshot->transform->mapRect(bounds);
GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0;
LayerSize size(bounds.getWidth(), bounds.getHeight());
Layer* layer = mCaches.layerCache.get(size, previousFbo);
Layer* layer = mCaches.layerCache.get(size);
if (!layer) {
return false;
}
glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
// Clear the FBO
glDisable(GL_SCISSOR_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
layer->mode = mode;
layer->alpha = alpha / 255.0f;
layer->alpha = alpha;
layer->layer.set(bounds);
// Save the layer in the snapshot
snapshot->flags |= Snapshot::kFlagIsLayer;
snapshot->layer = layer;
snapshot->fbo = layer->fbo;
// TODO: Temporary until real layer support is implemented
snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
// TODO: Temporary until real layer support is implemented
snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
snapshot->height = bounds.getHeight();
snapshot->flags |= Snapshot::kFlagDirtyOrtho;
snapshot->orthoMatrix.load(mOrthoMatrix);
// Copy the framebuffer into the layer
glBindTexture(GL_TEXTURE_2D, layer->texture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
bounds.getWidth(), bounds.getHeight(), 0);
// Clear the framebuffer where the layer will draw
glScissor(bounds.left, mHeight - bounds.bottom, bounds.getWidth(), bounds.getHeight());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
if (flags & SkCanvas::kClipToLayer_SaveFlag) {
mSnapshot->clipTransformed(bounds);
}
// Restore the initial clip
setScissorFromClip();
// Change the ortho projection
glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
mOrthoMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f);
return true;
}
@@ -330,22 +330,32 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
return;
}
// Unbind current FBO and restore previous one
// Most of the time, previous->fbo will be 0 to bind the default buffer
glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
// Restore the clip from the previous snapshot
const Rect& clip = *previous->clipRect;
glScissor(clip.left, previous->height - clip.bottom, clip.getWidth(), clip.getHeight());
glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
Layer* layer = current->layer;
const Rect& rect = layer->layer;
// FBOs are already drawn with a top-left origin, don't flip the texture
if (layer->alpha < 255) {
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ZERO, GL_SRC_ALPHA, GL_DST_ALPHA, GL_ZERO);
drawColorRect(rect.left, rect.top, rect.right, rect.bottom,
layer->alpha << 24, SkXfermode::kSrcOver_Mode, true, true);
glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
if (!mCaches.blend) {
glDisable(GL_BLEND);
}
}
// Layers are already drawn with a top-left origin, don't flip the texture
resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
layer->texture, layer->alpha, layer->mode, layer->blend);
drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
1.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
&mMeshVertices[0].texture[0], NULL, 0, true, true);
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
@@ -355,7 +365,6 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
if (!mCaches.layerCache.put(size, layer)) {
LAYER_LOGD("Deleting layer");
glDeleteFramebuffers(1, &layer->fbo);
glDeleteTextures(1, &layer->texture);
delete layer;
@@ -397,7 +406,7 @@ void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
void OpenGLRenderer::setScissorFromClip() {
const Rect& clip = *mSnapshot->clipRect;
glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight());
glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
}
const Rect& OpenGLRenderer::getClipBounds() {
@@ -405,8 +414,6 @@ const Rect& OpenGLRenderer::getClipBounds() {
}
bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
if (mSnapshot->invisible) return true;
Rect r(left, top, right, bottom);
mSnapshot->transform->mapRect(r);
return !mSnapshot->clipRect->intersects(r);
@@ -512,7 +519,6 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
}
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
if (mSnapshot->invisible) return;
const Rect& clip = *mSnapshot->clipRect;
drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
}
@@ -545,10 +551,10 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
float x, float y, SkPaint* paint) {
if (mSnapshot->invisible || text == NULL || count == 0 ||
(paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
return;
}
paint->setAntiAlias(true);
float scaleX = paint->getTextScaleX();
bool applyScaleX = scaleX < 0.9999f || scaleX > 1.0001f;
@@ -619,8 +625,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
}
void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
if (mSnapshot->invisible) return;
GLuint textureUnit = 0;
glActiveTexture(gTextureUnits[textureUnit]);
@@ -778,6 +782,7 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t
}
}
// Same values used by Skia
#define kStdStrikeThru_Offset (-6.0f / 21.0f)
#define kStdUnderline_Offset (1.0f / 9.0f)
#define kStdUnderline_Thickness (1.0f / 18.0f)
@@ -830,7 +835,7 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
}
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode, bool ignoreTransform) {
int color, SkXfermode::Mode mode, bool ignoreTransform, bool ignoreBlending) {
// If a shader is set, preserve only the alpha
if (mShader) {
color |= 0x00ffffff;
@@ -854,8 +859,10 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
mColorFilter->describe(description, mExtensions);
}
// Setup the blending mode
chooseBlending(alpha < 255 || (mShader && mShader->blend()), mode, description);
if (!ignoreBlending) {
// Setup the blending mode
chooseBlending(alpha < 255 || (mShader && mShader->blend()), mode, description);
}
// Build and use the appropriate shader
useProgram(mCaches.programCache.get(description));
@@ -905,7 +912,8 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) {
GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount,
bool swapSrcDst, bool ignoreTransform) {
ProgramDescription description;
description.hasTexture = true;
if (mColorFilter) {
@@ -915,10 +923,15 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
mModelView.loadTranslate(left, top, 0.0f);
mModelView.scale(right - left, bottom - top, 1.0f);
chooseBlending(blend || alpha < 1.0f, mode, description);
chooseBlending(blend || alpha < 1.0f, mode, description, swapSrcDst);
useProgram(mCaches.programCache.get(description));
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
if (!ignoreTransform) {
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
} else {
mat4 m;
mCaches.currentProgram->set(mOrthoMatrix, mModelView, m);
}
// Texture
bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0);
@@ -948,7 +961,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
}
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
ProgramDescription& description) {
ProgramDescription& description, bool swapSrcDst) {
blend = blend || mode != SkXfermode::kSrcOver_Mode;
if (blend) {
if (mode < SkXfermode::kPlus_Mode) {
@@ -956,8 +969,8 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
glEnable(GL_BLEND);
}
GLenum sourceMode = gBlends[mode].src;
GLenum destMode = gBlends[mode].dst;
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);
@@ -970,6 +983,7 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
// the blending, turn blending off here
if (mExtensions.hasFramebufferFetch()) {
description.framebufferMode = mode;
description.swapSrcDst = swapSrcDst;
}
if (mCaches.blend) {

View File

@@ -166,9 +166,11 @@ private:
* @param color The rectangle's ARGB color, defined as a packed 32 bits word
* @param mode The Skia xfermode to use
* @param ignoreTransform True if the current transform should be ignored
* @paran ignoreBlending True if the blending is set by the caller
*/
void drawColorRect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode, bool ignoreTransform = false);
int color, SkXfermode::Mode mode, bool ignoreTransform = false,
bool ignoreBlending = false);
/**
* Draws a textured rectangle with the specified texture. The specified coordinates
@@ -216,10 +218,13 @@ private:
* @param texCoords The texture coordinates of each vertex
* @param indices The indices of the vertices, can be NULL
* @param elementsCount The number of elements in the mesh, required by indices
* @param swapSrcDst Whether or not the src and dst blending operations should be swapped
* @param ignoreTransform True if the current transform should be ignored
*/
void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
float alpha, SkXfermode::Mode mode, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount = 0);
GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount = 0,
bool swapSrcDst = false, bool ignoreTransform = false);
/**
* Prepares the renderer to draw the specified shadow.
@@ -322,8 +327,13 @@ private:
* Enable or disable blending as necessary. This function sets the appropriate
* blend function based on the specified xfermode.
*/
inline void chooseBlending(bool blend, SkXfermode::Mode mode, ProgramDescription& description);
inline void chooseBlending(bool blend, SkXfermode::Mode mode, ProgramDescription& description,
bool swapSrcDst = false);
/**
* Safely retrieves the mode from the specified xfermode. If the specified
* xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
*/
inline SkXfermode::Mode getXfermode(SkXfermode* mode);
/**

View File

@@ -119,6 +119,8 @@ const char* gFS_Main_FragColor =
" gl_FragColor = fragColor;\n";
const char* gFS_Main_FragColor_Blend =
" gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n";
const char* gFS_Main_FragColor_Blend_Swap =
" gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n";
const char* gFS_Main_ApplyColorOp[4] = {
// None
"",
@@ -376,7 +378,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (!blendFramebuffer) {
shader.append(gFS_Main_FragColor);
} else {
shader.append(gFS_Main_FragColor_Blend);
shader.append(!description.swapSrcDst ?
gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap);
}
}
// End the shader

View File

@@ -35,7 +35,7 @@ namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Debug
#define DEBUG_PROGRAM_CACHE 1
#define DEBUG_PROGRAM_CACHE 0
// Debug
#if DEBUG_PROGRAM_CACHE
@@ -44,6 +44,9 @@ namespace uirenderer {
#define PROGRAM_LOGD(...)
#endif
/*
* IMPORTANT: All 32 bits are used, switch to a long.
*/
#define PROGRAM_KEY_TEXTURE 0x1
#define PROGRAM_KEY_A8_TEXTURE 0x2
#define PROGRAM_KEY_BITMAP 0x4
@@ -53,6 +56,7 @@ namespace uirenderer {
#define PROGRAM_KEY_COLOR_LIGHTING 0x40
#define PROGRAM_KEY_COLOR_BLEND 0x80
#define PROGRAM_KEY_BITMAP_NPOT 0x100
#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
@@ -70,6 +74,9 @@ namespace uirenderer {
// Types
///////////////////////////////////////////////////////////////////////////////
/*
* IMPORTANT: All 32 bits are used, switch to a long.
*/
typedef uint32_t programid;
///////////////////////////////////////////////////////////////////////////////
@@ -95,7 +102,7 @@ struct ProgramDescription {
shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false),
bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE),
colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode),
framebufferMode(SkXfermode::kClear_Mode) {
framebufferMode(SkXfermode::kClear_Mode), swapSrcDst(false) {
}
// Texturing
@@ -118,6 +125,7 @@ struct ProgramDescription {
// Framebuffer blending (requires Extensions.hasFramebufferFetch())
// Ignored for all values < SkXfermode::kPlus_Mode
SkXfermode::Mode framebufferMode;
bool swapSrcDst;
inline uint32_t getEnumForWrap(GLenum wrap) const {
switch (wrap) {
@@ -163,6 +171,7 @@ struct ProgramDescription {
break;
}
key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
return key;
}
}; // struct ProgramDescription

View File

@@ -43,7 +43,7 @@ namespace uirenderer {
*/
class Snapshot: public LightRefBase<Snapshot> {
public:
Snapshot(): invisible(false), flags(0), previous(NULL), layer(NULL), fbo(0) {
Snapshot(): flags(0), previous(NULL), layer(NULL) {
transform = &mTransformRoot;
clipRect = &mClipRectRoot;
}
@@ -53,13 +53,7 @@ public:
* the previous snapshot.
*/
Snapshot(const sp<Snapshot>& s, int saveFlags):
height(s->height),
invisible(s->invisible),
flags(0),
previous(s),
layer(NULL),
fbo(s->fbo),
viewport(s->viewport) {
flags(0), previous(s), layer(NULL) {
if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
mTransformRoot.load(*s->transform);
transform = &mTransformRoot;
@@ -96,24 +90,31 @@ public:
* a new layer.
*/
kFlagIsLayer = 0x2,
/**
* Indicates that this snapshot has changed the ortho matrix.
*/
kFlagDirtyOrtho = 0x4,
/**
* Indicates that the local clip should be recomputed.
*/
kFlagDirtyLocalClip = 0x8,
kFlagDirtyLocalClip = 0x4,
};
/**
* Intersects the current clip with the new clip rectangle.
* Modifies the current clip with the new clip rectangle and
* the specified operation. The specified rectangle is transformed
* by this snapshot's trasnformation.
*/
bool clip(float left, float top, float right, float bottom, SkRegion::Op op) {
bool clipped = false;
bool clip(float left, float top, float right, float bottom,
SkRegion::Op op = SkRegion::kIntersect_Op) {
Rect r(left, top, right, bottom);
transform->mapRect(r);
return clipTransformed(r, op);
}
/**
* Modifies the current clip with the new clip rectangle and
* the specified operation. The specified rectangle is considered
* already transformed.
*/
bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) {
bool clipped = false;
switch (op) {
case SkRegion::kDifference_Op:
@@ -162,29 +163,6 @@ public:
return mLocalClip;
}
// TODO: Temporary
void resetTransform(float x, float y, float z) {
transform = &mTransformRoot;
transform->loadTranslate(x, y, z);
}
// TODO: Temporary
void resetClip(float left, float top, float right, float bottom) {
clipRect = &mClipRectRoot;
clipRect->set(left, top, right, bottom);
flags |= Snapshot::kFlagClipSet | Snapshot::kFlagDirtyLocalClip;
}
/**
* Height of the framebuffer the snapshot is rendering into.
*/
int height;
/**
* If true, the layer won't be rendered.
*/
bool invisible;
/**
* Dirty flags.
*/
@@ -199,17 +177,6 @@ public:
* Only set when the flag kFlagIsLayer is set.
*/
Layer* layer;
GLuint fbo;
/**
* Current viewport.
*/
Rect viewport;
/**
* Contains the previous ortho matrix.
*/
mat4 orthoMatrix;
/**
* Local transformation. Holds the current translation, scale and

View File

@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.test.hwui">
package="com.android.test.hwui">
<application
android:label="HwUi"
@@ -70,6 +70,15 @@
</intent-filter>
</activity>
<activity
android:name="NewLayersActivity"
android:label="_NewLayers">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="XfermodeActivity"
android:label="_Xfermodes"
@@ -164,6 +173,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="TransparentListActivity"
android:label="_TransparentList">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="MoreShadersActivity"

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -15,7 +15,7 @@
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
@SuppressWarnings({"UnusedDeclaration"})
public class NewLayersActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new LayersView(this));
}
static class LayersView extends View {
private Paint mLayerPaint;
private final Paint mRectPaint;
LayersView(Context c) {
super(c);
mLayerPaint = new Paint();
mRectPaint = new Paint();
mRectPaint.setAntiAlias(true);
mRectPaint.setTextSize(24.0f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(128, 255, 128);
canvas.translate(140.0f, 100.0f);
mLayerPaint.setAlpha(127);
int count = canvas.saveLayer(0.0f, 0.0f, 200.0f, 100.0f, mLayerPaint,
Canvas.ALL_SAVE_FLAG);
mRectPaint.setColor(0x7fff0000);
canvas.drawRect(-20.0f, -20.0f, 220.0f, 120.0f, mRectPaint);
mRectPaint.setColor(0xff000000);
canvas.drawText("This is a very long string to overlap between layers and framebuffer",
-100.0f, 50.0f, mRectPaint);
canvas.restoreToCount(count);
canvas.translate(0.0f, 200.0f);
mLayerPaint.setAlpha(127);
count = canvas.saveLayer(0.0f, 0.0f, 200.0f, 100.0f, mLayerPaint,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
mRectPaint.setColor(0x7fff0000);
canvas.drawRect(-20.0f, -20.0f, 220.0f, 120.0f, mRectPaint);
mRectPaint.setColor(0xff000000);
canvas.drawText("This is a very long string to overlap between layers and framebuffer",
-100.0f, 50.0f, mRectPaint);
canvas.restoreToCount(count);
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.os.Bundle;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.os.Bundle;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.os.Bundle;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.graphics.drawable.Drawable;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.ContextMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
@SuppressWarnings({"UnusedDeclaration"})
public class TransparentListActivity extends Activity {
private static final String[] DATA_LIST = {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
"Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
"Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
"Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
"Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
"Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
"British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
"Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
"Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
"Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
"Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
"Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
"East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
"Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
"Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
"French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
"Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
"Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
"Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
"Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
"Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
"Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
"Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
"Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
"Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
"Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
"Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
"Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
"Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
"Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
"Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
"Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
"Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
"Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
"Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
"The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
"Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
"Ukraine", "United Arab Emirates", "United Kingdom",
"United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
"Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
"Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.default_wallpaper));
setContentView(R.layout.list_activity);
ListAdapter adapter = new SimpleListAdapter(this);
ListView list = (ListView) findViewById(R.id.list);
list.setAdapter(adapter);
list.setCacheColorHint(0);
registerForContextMenu(list);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Context menu");
menu.add("List item 1");
menu.add("List item 2");
menu.add("List item 3");
}
private static class SimpleListAdapter extends ArrayAdapter<String> {
public SimpleListAdapter(Context context) {
super(context, android.R.layout.simple_list_item_1, DATA_LIST);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = (TextView) super.getView(position, convertView, parent);
final Resources r = getContext().getResources();
final DisplayMetrics metrics = r.getDisplayMetrics();
v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
null, null, null);
return v;
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.android.test.hwui;
package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;