Merge "Add colored rectangles implementation in OpenGLRenderer."

This commit is contained in:
Romain Guy
2010-06-24 19:32:44 -07:00
committed by Android (Google) Code Review
11 changed files with 395 additions and 26 deletions

View File

@@ -186,10 +186,11 @@ class GLES20Canvas extends Canvas {
@Override
public boolean getClipBounds(Rect bounds) {
// TODO: Implement
return false;
return nGetClipBounds(mRenderer, bounds);
}
private native boolean nGetClipBounds(int renderer, Rect bounds);
@Override
public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
// TODO: Implement

View File

@@ -22,9 +22,22 @@
#include <SkXfermode.h>
#include <OpenGLRenderer.h>
#include <Rect.h>
#include <ui/Rect.h>
namespace android {
using namespace uirenderer;
// ----------------------------------------------------------------------------
// Java APIs
// ----------------------------------------------------------------------------
static struct {
jclass clazz;
jmethodID set;
} gRectClassInfo;
// ----------------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------------
@@ -90,6 +103,17 @@ static bool android_view_GLES20Renderer_clipRect(JNIEnv* env, jobject canvas,
return renderer->clipRect(float(left), float(top), float(right), float(bottom));
}
static bool android_view_GLES20Renderer_getClipBounds(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jobject rect) {
const android::uirenderer::Rect& bounds(renderer->getClipBounds());
env->CallVoidMethod(rect, gRectClassInfo.set,
int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
return !bounds.isEmpty();
}
// ----------------------------------------------------------------------------
// Transforms
// ----------------------------------------------------------------------------
@@ -153,6 +177,9 @@ static JNINativeMethod gMethods[] = {
{ "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF },
{ "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect },
{ "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
(void*) android_view_GLES20Renderer_getClipBounds },
{ "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate },
{ "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate },
{ "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale },
@@ -164,7 +191,19 @@ static JNINativeMethod gMethods[] = {
{ "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor },
};
#define FIND_CLASS(var, className) \
var = env->FindClass(className); \
LOG_FATAL_IF(! var, "Unable to find class " className); \
var = jclass(env->NewGlobalRef(var));
#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
var = env->GetMethodID(clazz, methodName, methodDescriptor); \
LOG_FATAL_IF(! var, "Unable to find method " methodName);
int register_android_view_GLES20Canvas(JNIEnv* env) {
FIND_CLASS(gRectClassInfo.clazz, "android/graphics/Rect");
GET_METHOD_ID(gRectClassInfo.set, gRectClassInfo.clazz, "set", "(IIII)V");
return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#define LOG_TAG "UIMatrix"
#define LOG_TAG "Matrix"
#include <math.h>
#include <stdlib.h>
@@ -27,6 +27,7 @@
#include "Matrix.h"
namespace android {
namespace uirenderer {
void Matrix4::loadIdentity() {
mMat[0] = 1.0f;
@@ -175,6 +176,21 @@ void Matrix4::loadOrtho(float left, float right, float bottom, float top, float
mMat[14] = -(far + near) / (far - near);
}
#define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
void Matrix4::mapRect(Rect& r) const {
const float sx = mMat[0];
const float sy = mMat[5];
const float tx = mMat[12];
const float ty = mMat[13];
MUL_ADD_STORE(r.left, sx, tx);
MUL_ADD_STORE(r.right, sx, tx);
MUL_ADD_STORE(r.top, sy, ty);
MUL_ADD_STORE(r.bottom, sy, ty);
}
void Matrix4::dump() const {
LOGD("Matrix4[");
LOGD(" %f %f %f %f", mMat[0], mMat[4], mMat[ 8], mMat[12]);
@@ -184,4 +200,5 @@ void Matrix4::dump() const {
LOGD("]");
}
};
}; // namespace uirenderer
}; // namespace android

View File

@@ -14,12 +14,15 @@
* limitations under the License.
*/
#ifndef ANDROID_MATRIX_H
#define ANDROID_MATRIX_H
#ifndef ANDROID_UI_MATRIX_H
#define ANDROID_UI_MATRIX_H
#include <SkMatrix.h>
#include "Rect.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Classes
@@ -83,6 +86,8 @@ public:
void copyTo(float* v) const;
void copyTo(SkMatrix& v) const;
void mapRect(Rect& r) const;
void dump() const;
private:
@@ -103,6 +108,7 @@ private:
typedef Matrix4 mat4;
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_MATRIX_H
#endif // ANDROID_UI_MATRIX_H

View File

@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/Log.h>
#include <GLES2/gl2.h>
@@ -32,6 +33,129 @@
#include "Matrix.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
#define SOLID_WHITE { 1.0f, 1.0f, 1.0f, 1.0f }
#define P(x, y) { x, y }
///////////////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////////////
const Vertex gDrawColorVertices[] = {
{ P(0.0f, 0.0f), SOLID_WHITE },
{ P(1.0f, 0.0f), SOLID_WHITE },
{ P(0.0f, 1.0f), SOLID_WHITE },
{ P(1.0f, 1.0f), SOLID_WHITE }
};
///////////////////////////////////////////////////////////////////////////////
// Shaders
///////////////////////////////////////////////////////////////////////////////
#define SHADER_SOURCE(name, source) const char* name = #source
#include "shaders/drawColor.vert"
#include "shaders/drawColor.frag"
Program::Program(const char* vertex, const char* fragment) {
vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
id = glCreateProgram();
glAttachShader(id, vertexShader);
glAttachShader(id, fragmentShader);
glLinkProgram(id);
GLint status;
glGetProgramiv(id, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
GLint infoLen = 0;
glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* log = (char*) malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(id, infoLen, 0, log);
LOGE("Error while linking shaders: %s", log);
delete log;
}
glDeleteProgram(id);
}
}
Program::~Program() {
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(id);
}
void Program::use() {
glUseProgram(id);
}
int Program::addAttrib(const char* name) {
int slot = glGetAttribLocation(id, name);
attributes.add(name, slot);
return slot;
}
int Program::getAttrib(const char* name) {
return attributes.valueFor(name);
}
int Program::addUniform(const char* name) {
int slot = glGetUniformLocation(id, name);
uniforms.add(name, slot);
return slot;
}
int Program::getUniform(const char* name) {
return uniforms.valueFor(name);
}
GLuint Program::buildShader(const char* source, GLenum type) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, 0);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
// Some drivers return wrong values for GL_INFO_LOG_LENGTH
// use a fixed size instead
GLchar log[512];
glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]);
LOGE("Error while compiling shader: %s", log);
glDeleteShader(shader);
}
return shader;
}
DrawColorProgram::DrawColorProgram():
Program(gDrawColorVertexShader, gDrawColorFragmentShader) {
position = addAttrib("position");
color = addAttrib("color");
projection = addUniform("projection");
modelView = addUniform("modelView");
}
///////////////////////////////////////////////////////////////////////////////
// Support
///////////////////////////////////////////////////////////////////////////////
const Rect& Snapshot::getMappedClip() {
if (flags & kFlagDirtyTransform) {
flags &= ~kFlagDirtyTransform;
mappedClip.set(clipRect);
transform.mapRect(mappedClip);
}
return mappedClip;
}
///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
@@ -39,6 +163,8 @@ namespace android {
OpenGLRenderer::OpenGLRenderer() {
LOGD("Create OpenGLRenderer");
mDrawColorShader = new DrawColorProgram;
}
OpenGLRenderer::~OpenGLRenderer() {
@@ -114,7 +240,6 @@ int OpenGLRenderer::saveSnapshot() {
}
bool OpenGLRenderer::restoreSnapshot() {
// TODO: handle local transformations
bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
mSaveCount--;
@@ -132,18 +257,22 @@ bool OpenGLRenderer::restoreSnapshot() {
void OpenGLRenderer::translate(float dx, float dy) {
mSnapshot->transform.translate(dx, dy, 0.0f);
mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::rotate(float degrees) {
mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::scale(float sx, float sy) {
mSnapshot->transform.scale(sx, sy, 1.0f);
mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
mSnapshot->transform.load(*matrix);
mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
@@ -153,6 +282,7 @@ void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
mat4 m(*matrix);
mSnapshot->transform.multiply(m);
mSnapshot->flags |= Snapshot::kFlagDirtyTransform;
}
///////////////////////////////////////////////////////////////////////////////
@@ -160,12 +290,15 @@ void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::setScissorFromClip() {
Rect* clip = &(mSnapshot->clipRect);
glScissor(clip->left, clip->top, clip->getWidth(), clip->getHeight());
const Rect& clip = mSnapshot->getMappedClip();
glScissor(clip.left, clip.top, clip.getWidth(), clip.getHeight());
}
const Rect& OpenGLRenderer::getClipBounds() {
return mSnapshot->clipRect;
}
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
// TODO: take local translate transform into account
bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom);
if (clipped) {
mSnapshot->flags |= Snapshot::kFlagClipSet;
@@ -179,7 +312,41 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
LOGD("Drawing color");
GLfloat a = ((color >> 24) & 0xFF) / 255.0f;
GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
GLfloat g = ((color >> 8) & 0xFF) / 255.0f;
GLfloat b = ((color ) & 0xFF) / 255.0f;
// TODO Optimize this section
const Rect& clip = mSnapshot->getMappedClip();
mat4 modelView;
modelView.loadScale(clip.getWidth(), clip.getHeight(), 1.0f);
modelView.translate(clip.left, clip.top, 0.0f);
float matrix[16];
modelView.copyTo(matrix);
// TODO Optimize this section
mDrawColorShader->use();
glUniformMatrix4fv(mDrawColorShader->projection, 1, GL_FALSE, &mOrthoMatrix[0]);
glUniformMatrix4fv(mDrawColorShader->modelView, 1, GL_FALSE, &matrix[0]);
glEnableVertexAttribArray(mDrawColorShader->position);
GLsizei stride = sizeof(Vertex);
const GLvoid* p = &gDrawColorVertices[0].position[0];
glVertexAttribPointer(mDrawColorShader->position, 2, GL_FLOAT, GL_FALSE, stride, p);
glVertexAttrib4f(mDrawColorShader->color, r, g, b, a);
GLsizei vertexCount = sizeof(gDrawColorVertices) / sizeof(Vertex);
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexCount);
glDisableVertexAttribArray(mDrawColorShader->position);
glDisableVertexAttribArray(mDrawColorShader->color);
}
}; // namespace uirenderer
}; // namespace android

View File

@@ -14,18 +14,23 @@
* limitations under the License.
*/
#ifndef ANDROID_OPENGL_RENDERER_H
#define ANDROID_OPENGL_RENDERER_H
#ifndef ANDROID_UI_OPENGL_RENDERER_H
#define ANDROID_UI_OPENGL_RENDERER_H
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <SkMatrix.h>
#include <SkXfermode.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include "Matrix.h"
#include "Rect.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Support
@@ -36,14 +41,20 @@ public:
Snapshot() {
}
Snapshot(const sp<Snapshot> s): transform(s->transform), clipRect(s->clipRect),
flags(0), previous(s) {
Snapshot(const sp<Snapshot> s):
transform(s->transform),
clipRect(s->clipRect),
flags(kFlagDirtyTransform),
previous(s) {
}
enum Flags {
kFlagClipSet = 0x1,
kFlagDirtyTransform = 0x2,
};
const Rect& getMappedClip();
// Local transformations
mat4 transform;
@@ -55,7 +66,58 @@ public:
// Previous snapshot in the frames stack
sp<Snapshot> previous;
}; // struct Snapshot
private:
// Clipping rectangle mapped with the transform
Rect mappedClip;
}; // class Snapshot
struct Vertex {
float position[2];
float color[4];
}; // struct Vertex
typedef char* shader;
class Program: public LightRefBase<Program> {
public:
Program(const char* vertex, const char* fragment);
~Program();
void use();
protected:
int addAttrib(const char* name);
int getAttrib(const char* name);
int addUniform(const char* name);
int getUniform(const char* name);
private:
GLuint buildShader(const char* source, GLenum type);
// Handle of the OpenGL program
GLuint id;
// Handles of the shaders
GLuint vertexShader;
GLuint fragmentShader;
// Keeps track of attributes and uniforms slots
KeyedVector<const char*, int> attributes;
KeyedVector<const char*, int> uniforms;
}; // class Program
class DrawColorProgram: public Program {
public:
DrawColorProgram();
int position;
int color;
int projection;
int modelView;
};
///////////////////////////////////////////////////////////////////////////////
// Renderer
@@ -82,6 +144,7 @@ public:
void getMatrix(SkMatrix* matrix);
void concatMatrix(SkMatrix* matrix);
const Rect& getClipBounds();
bool clipRect(float left, float top, float right, float bottom);
void drawColor(int color, SkXfermode::Mode mode);
@@ -104,8 +167,12 @@ private:
Snapshot mFirstSnapshot;
// Current state
sp<Snapshot> mSnapshot;
// Shaders
sp<DrawColorProgram> mDrawColorShader;
}; // class OpenGLRenderer
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_OPENGL_RENDERER_H
#endif // ANDROID_UI_OPENGL_RENDERER_H

View File

@@ -14,10 +14,11 @@
* limitations under the License.
*/
#ifndef ANDROID_RECT_H
#define ANDROID_RECT_H
#ifndef ANDROID_UI_RECT_H
#define ANDROID_UI_RECT_H
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Structs
@@ -29,7 +30,19 @@ struct Rect {
float right;
float bottom;
Rect(): left(0), top(0), right(0), bottom(0) { }
Rect():
left(0),
top(0),
right(0),
bottom(0) {
}
Rect(float left, float top, float right, float bottom):
left(left),
top(top),
right(right),
bottom(bottom) {
}
Rect(const Rect& r) {
set(r);
@@ -120,6 +133,7 @@ struct Rect {
}; // struct Rect
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_RECT_H

View File

@@ -0,0 +1,11 @@
SHADER_SOURCE(gDrawColorFragmentShader,
precision mediump float;
varying vec4 outColor;
void main(void) {
gl_FragColor = outColor;
}
);

View File

@@ -0,0 +1,16 @@
SHADER_SOURCE(gDrawColorVertexShader,
attribute vec4 position;
attribute vec4 color;
uniform mat4 projection;
uniform mat4 modelView;
varying vec4 outColor;
void main(void) {
outColor = color;
gl_Position = projection * modelView * position;
}
);

View File

@@ -207,7 +207,7 @@ public final class CallManager {
* java.lang.Object) registerForPreciseCallStateChanged()}.
*
* @exception CallStateException if active call is ringing, waiting, or
* dialing/alerting, or heldCall can<EFBFBD>t be active.
* dialing/alerting, or heldCall can't be active.
* In these cases, this operation may not be performed.
*/
public void switchHoldingAndActive(Call heldCall) throws CallStateException {

View File

@@ -18,14 +18,13 @@ package com.google.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import static android.util.Log.d;
@SuppressWarnings({"UnusedDeclaration"})
public class HwUiActivity extends Activity {
private static final String LOG_TAG = "HwUi";
@@ -42,15 +41,47 @@ public class HwUiActivity extends Activity {
}
static class DirtyBitmapView extends View {
private final Paint mPaint;
DirtyBitmapView(Context c) {
super(c);
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(255, 0, 0);
canvas.drawRGB(255, 255, 255);
mPaint.setColor(0xffff0000);
canvas.drawRect(200.0f, 0.0f, 220.0f, 20.0f, mPaint);
canvas.save();
canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
canvas.restore();
canvas.save();
canvas.scale(2.0f, 2.0f);
canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
canvas.restore();
canvas.save();
canvas.translate(20.0f, 20.0f);
canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
canvas.restore();
canvas.scale(2.0f, 2.0f);
canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
mPaint.setColor(0xff00ff00);
canvas.drawRect(0.0f, 0.0f, 20.0f, 20.0f, mPaint);
mPaint.setColor(0xff0000ff);
canvas.drawRect(20.0f, 0.0f, 40.0f, 20.0f, mPaint);
}
}
}