Add support for transformations.

This change adds partial support for the following transforms:
- scale()
- translate()
- rotate()
- setMatrix()
- getMatrix()

The transform is stored in a snapshot and saved/restored as needed.
The transform is currently not applied to the clip rect and is not
mapped to the vertex shader.

Change-Id: Id48993453311200804149917d0c126a4d0471226
This commit is contained in:
Romain Guy
2010-06-23 17:47:49 -07:00
parent bb9524b6bd
commit f6a11b8a9e
7 changed files with 253 additions and 79 deletions

View File

@@ -212,8 +212,10 @@ class GLES20Canvas extends Canvas {
@Override
public void translate(float dx, float dy) {
// TODO: Implement
nTranslate(mRenderer, dx, dy);
}
private native void nTranslate(int renderer, float dx, float dy);
@Override
public void skew(float sx, float sy) {
@@ -222,30 +224,39 @@ class GLES20Canvas extends Canvas {
@Override
public void rotate(float degrees) {
// TODO: Implement
nRotate(mRenderer, degrees);
}
private native void nRotate(int renderer, float degrees);
@Override
public void scale(float sx, float sy) {
// TODO: Implement
nScale(mRenderer, sx, sy);
}
private native void nScale(int renderer, float sx, float sy);
@Override
public void setMatrix(Matrix matrix) {
// TODO: Implement
nSetMatrix(mRenderer, matrix.native_instance);
}
private native void nSetMatrix(int renderer, int matrix);
@Override
public void getMatrix(Matrix ctm) {
// TODO: Implement
public void getMatrix(Matrix matrix) {
nGetMatrix(mRenderer, matrix.native_instance);
}
private native void nGetMatrix(int renderer, int matrix);
@Override
public void concat(Matrix matrix) {
// TODO: Implement
nConcatMatrix(mRenderer, matrix.native_instance);
}
private native void nConcatMatrix(int renderer, int matrix);
///////////////////////////////////////////////////////////////////////////
// State management
///////////////////////////////////////////////////////////////////////////

View File

@@ -18,12 +18,11 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <SkMatrix.h>
#include <SkXfermode.h>
#include <OpenGLRenderer.h>
#define UI ((OpenGLRenderer*) renderer)
namespace android {
// ----------------------------------------------------------------------------
@@ -34,73 +33,104 @@ static OpenGLRenderer* android_view_GLES20Renderer_createRenderer(JNIEnv* env, j
return new OpenGLRenderer;
}
static void android_view_GLES20Renderer_destroyRenderer(JNIEnv* env, jobject canvas, jint renderer) {
delete UI;
static void android_view_GLES20Renderer_destroyRenderer(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
delete renderer;
}
// ----------------------------------------------------------------------------
// Setup
// ----------------------------------------------------------------------------
static void android_view_GLES20Renderer_setViewport(JNIEnv* env, jobject canvas, jint renderer,
jint width, jint height) {
UI->setViewport(width, height);
static void android_view_GLES20Renderer_setViewport(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jint width, jint height) {
renderer->setViewport(width, height);
}
static void android_view_GLES20Renderer_prepare(JNIEnv* env, jobject canvas, jint renderer) {
UI->prepare();
static void android_view_GLES20Renderer_prepare(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
renderer->prepare();
}
// ----------------------------------------------------------------------------
// State
// ----------------------------------------------------------------------------
static jint android_view_GLES20Renderer_save(JNIEnv* env, jobject canvas, jint renderer,
static jint android_view_GLES20Renderer_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer,
jint flags) {
return UI->save(flags);
return renderer->save(flags);
}
static jint android_view_GLES20Renderer_getSaveCount(JNIEnv* env, jobject canvas, jint renderer) {
return UI->getSaveCount();
static jint android_view_GLES20Renderer_getSaveCount(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
return renderer->getSaveCount();
}
static void android_view_GLES20Renderer_restore(JNIEnv* env, jobject canvas, jint renderer) {
UI->restore();
static void android_view_GLES20Renderer_restore(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
renderer->restore();
}
static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canvas, jint renderer,
jint saveCount) {
UI->restoreToCount(saveCount);
static void android_view_GLES20Renderer_restoreToCount(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jint saveCount) {
renderer->restoreToCount(saveCount);
}
// ----------------------------------------------------------------------------
// Clipping
// ----------------------------------------------------------------------------
static bool android_view_GLES20Renderer_clipRectF(JNIEnv* env, jobject canvas, jint renderer,
jfloat left, jfloat top, jfloat right, jfloat bottom) {
return UI->clipRect(left, top, right, bottom);
static bool android_view_GLES20Renderer_clipRectF(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) {
return renderer->clipRect(left, top, right, bottom);
}
static bool android_view_GLES20Renderer_clipRect(JNIEnv* env, jobject canvas, jint renderer,
jint left, jint top, jint right, jint bottom) {
static bool android_view_GLES20Renderer_clipRect(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom) {
return renderer->clipRect(float(left), float(top), float(right), float(bottom));
}
return UI->clipRect(float(left), float(top), float(right), float(bottom));
// ----------------------------------------------------------------------------
// Transforms
// ----------------------------------------------------------------------------
static void android_view_GLES20Renderer_translate(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat dx, jfloat dy) {
renderer->translate(dx, dy);
}
static void android_view_GLES20Renderer_rotate(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat degrees) {
renderer->rotate(degrees);
}
static void android_view_GLES20Renderer_scale(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jfloat sx, jfloat sy) {
renderer->scale(sx, sy);
}
static void android_view_GLES20Renderer_setMatrix(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, SkMatrix* matrix) {
renderer->setMatrix(matrix);
}
static void android_view_GLES20Renderer_getMatrix(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, SkMatrix* matrix) {
renderer->getMatrix(matrix);
}
static void android_view_GLES20Renderer_concatMatrix(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, SkMatrix* matrix) {
renderer->concatMatrix(matrix);
}
// ----------------------------------------------------------------------------
// Drawing
// ----------------------------------------------------------------------------
static void android_view_GLES20Renderer_drawColor(JNIEnv* env, jobject canvas, jint renderer,
jint color, jint mode) {
UI->drawColor(color, (SkXfermode::Mode) mode);
static void android_view_GLES20Renderer_drawColor(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer, jint color, jint mode) {
renderer->drawColor(color, (SkXfermode::Mode) mode);
}
// ----------------------------------------------------------------------------
@@ -123,6 +153,14 @@ static JNINativeMethod gMethods[] = {
{ "nClipRect", "(IFFFF)Z", (void*) android_view_GLES20Renderer_clipRectF },
{ "nClipRect", "(IIIII)Z", (void*) android_view_GLES20Renderer_clipRect },
{ "nTranslate", "(IFF)V", (void*) android_view_GLES20Renderer_translate },
{ "nRotate", "(IF)V", (void*) android_view_GLES20Renderer_rotate },
{ "nScale", "(IFF)V", (void*) android_view_GLES20Renderer_scale },
{ "nSetMatrix", "(II)V", (void*) android_view_GLES20Renderer_setMatrix },
{ "nGetMatrix", "(II)V", (void*) android_view_GLES20Renderer_getMatrix },
{ "nConcatMatrix", "(II)V", (void*) android_view_GLES20Renderer_concatMatrix },
{ "nDrawColor", "(III)V", (void*) android_view_GLES20Renderer_drawColor },
};

View File

@@ -37,7 +37,10 @@ public class Matrix {
public static final int MPERSP_1 = 7; //!< use with getValues/setValues
public static final int MPERSP_2 = 8; //!< use with getValues/setValues
/* package */ int native_instance;
/**
* @hide
*/
public int native_instance;
/**
* Create an identity matrix

View File

@@ -22,30 +22,32 @@
#include <utils/Log.h>
#include <SkMatrix.h>
#include "Matrix.h"
namespace android {
void Matrix4::loadIdentity() {
mMat[0] = 1;
mMat[1] = 0;
mMat[2] = 0;
mMat[3] = 0;
mMat[0] = 1.0f;
mMat[1] = 0.0f;
mMat[2] = 0.0f;
mMat[3] = 0.0f;
mMat[4] = 0;
mMat[5] = 1;
mMat[6] = 0;
mMat[7] = 0;
mMat[4] = 0.0f;
mMat[5] = 1.0f;
mMat[6] = 0.0f;
mMat[7] = 0.0f;
mMat[8] = 0;
mMat[9] = 0;
mMat[10] = 1;
mMat[11] = 0;
mMat[8] = 0.0f;
mMat[9] = 0.0f;
mMat[10] = 1.0f;
mMat[11] = 0.0f;
mMat[12] = 0;
mMat[13] = 0;
mMat[14] = 0;
mMat[15] = 1;
mMat[12] = 0.0f;
mMat[13] = 0.0f;
mMat[14] = 0.0f;
mMat[15] = 1.0f;
}
void Matrix4::load(const float* v) {
@@ -56,6 +58,40 @@ void Matrix4::load(const Matrix4& v) {
memcpy(mMat, v.mMat, sizeof(mMat));
}
void Matrix4::load(const SkMatrix& v) {
memset(mMat, 0, sizeof(mMat));
mMat[0] = v[SkMatrix::kMScaleX];
mMat[4] = v[SkMatrix::kMSkewX];
mMat[12] = v[SkMatrix::kMTransX];
mMat[1] = v[SkMatrix::kMSkewY];
mMat[5] = v[SkMatrix::kMScaleY];
mMat[13] = v[SkMatrix::kMTransY];
mMat[3] = v[SkMatrix::kMPersp0];
mMat[7] = v[SkMatrix::kMPersp1];
mMat[15] = v[SkMatrix::kMPersp2];
mMat[10] = 1.0f;
}
void Matrix4::copyTo(SkMatrix& v) const {
v.reset();
v.set(SkMatrix::kMScaleX, mMat[0]);
v.set(SkMatrix::kMSkewX, mMat[4]);
v.set(SkMatrix::kMTransX, mMat[12]);
v.set(SkMatrix::kMSkewY, mMat[1]);
v.set(SkMatrix::kMScaleY, mMat[5]);
v.set(SkMatrix::kMTransY, mMat[13]);
v.set(SkMatrix::kMPersp0, mMat[3]);
v.set(SkMatrix::kMPersp1, mMat[7]);
v.set(SkMatrix::kMPersp2, mMat[15]);
}
void Matrix4::copyTo(float* v) const {
memcpy(v, mMat, sizeof(mMat));
}
@@ -75,13 +111,13 @@ void Matrix4::loadScale(float sx, float sy, float sz) {
}
void Matrix4::loadRotate(float angle, float x, float y, float z) {
mMat[3] = 0;
mMat[7] = 0;
mMat[11] = 0;
mMat[12] = 0;
mMat[13] = 0;
mMat[14] = 0;
mMat[15] = 1;
mMat[3] = 0.0f;
mMat[7] = 0.0f;
mMat[11] = 0.0f;
mMat[12] = 0.0f;
mMat[13] = 0.0f;
mMat[14] = 0.0f;
mMat[15] = 1.0f;
angle *= float(M_PI / 180.0f);
float c = cosf(angle);
@@ -131,9 +167,9 @@ void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
loadIdentity();
mMat[0] = 2 / (right - left);
mMat[5] = 2 / (top - bottom);
mMat[10] = -2 / (far - near);
mMat[0] = 2.0f / (right - left);
mMat[5] = 2.0f / (top - bottom);
mMat[10] = -2.0f / (far - near);
mMat[12] = -(right + left) / (right - left);
mMat[13] = -(top + bottom) / (top - bottom);
mMat[14] = -(far + near) / (far - near);

View File

@@ -17,6 +17,8 @@
#ifndef ANDROID_MATRIX_H
#define ANDROID_MATRIX_H
#include <SkMatrix.h>
namespace android {
///////////////////////////////////////////////////////////////////////////////
@@ -37,10 +39,15 @@ public:
load(v);
}
Matrix4(const SkMatrix& v) {
load(v);
}
void loadIdentity();
void load(const float* v);
void load(const Matrix4& v);
void load(const SkMatrix& v);
void loadTranslate(float x, float y, float z);
void loadScale(float sx, float sy, float sz);
@@ -74,10 +81,11 @@ public:
}
void copyTo(float* v) const;
void copyTo(SkMatrix& v) const;
void dump() const;
//private:
private:
inline float get(int i, int j) const {
return mMat[i * 4 + j];
}

View File

@@ -33,17 +33,22 @@
namespace android {
///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
OpenGLRenderer::OpenGLRenderer() {
LOGD("Create OpenGLRenderer");
mSnapshot = new Snapshot;
mSaveCount = 0;
}
OpenGLRenderer::~OpenGLRenderer() {
LOGD("Destroy OpenGLRenderer");
}
///////////////////////////////////////////////////////////////////////////////
// Setup
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::setViewport(int width, int height) {
glViewport(0, 0, width, height);
@@ -56,15 +61,23 @@ void OpenGLRenderer::setViewport(int width, int height) {
}
void OpenGLRenderer::prepare() {
mSnapshot = &mFirstSnapshot;
mSaveCount = 0;
glDisable(GL_SCISSOR_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
mSnapshot->clipRect.set(0.0f, 0.0f, mWidth, mHeight);
}
///////////////////////////////////////////////////////////////////////////////
// State management
///////////////////////////////////////////////////////////////////////////////
int OpenGLRenderer::getSaveCount() const {
return mSaveCount;
}
@@ -97,8 +110,7 @@ void OpenGLRenderer::restoreToCount(int saveCount) {
int OpenGLRenderer::saveSnapshot() {
mSnapshot = new Snapshot(mSnapshot);
mSaveCount++;
return mSaveCount;
return ++mSaveCount;
}
bool OpenGLRenderer::restoreSnapshot() {
@@ -106,14 +118,50 @@ bool OpenGLRenderer::restoreSnapshot() {
bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
mSaveCount--;
mSnapshot = mSnapshot->previous;
// Do not merge these two lines!
sp<Snapshot> previous = mSnapshot->previous;
mSnapshot = previous;
return restoreClip;
}
///////////////////////////////////////////////////////////////////////////////
// Transforms
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::translate(float dx, float dy) {
mSnapshot->transform.translate(dx, dy, 0.0f);
}
void OpenGLRenderer::rotate(float degrees) {
mSnapshot->transform.rotate(degrees, 0.0f, 0.0f, 1.0f);
}
void OpenGLRenderer::scale(float sx, float sy) {
mSnapshot->transform.scale(sx, sy, 1.0f);
}
void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
mSnapshot->transform.load(*matrix);
}
void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
mSnapshot->transform.copyTo(*matrix);
}
void OpenGLRenderer::concatMatrix(SkMatrix* matrix) {
mat4 m(*matrix);
mSnapshot->transform.multiply(m);
}
///////////////////////////////////////////////////////////////////////////////
// Clipping
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::setScissorFromClip() {
Rect clip = mSnapshot->clipRect;
glScissor(clip.left, clip.top, clip.getWidth(), clip.getHeight());
Rect* clip = &(mSnapshot->clipRect);
glScissor(clip->left, clip->top, clip->getWidth(), clip->getHeight());
}
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
@@ -126,6 +174,10 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)
return clipped;
}
///////////////////////////////////////////////////////////////////////////////
// Drawing
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
LOGD("Drawing color");
}

View File

@@ -17,24 +17,36 @@
#ifndef ANDROID_OPENGL_RENDERER_H
#define ANDROID_OPENGL_RENDERER_H
#include <SkMatrix.h>
#include <SkXfermode.h>
#include <utils/RefBase.h>
#include "Matrix.h"
#include "Rect.h"
namespace android {
///////////////////////////////////////////////////////////////////////////////
// Support
///////////////////////////////////////////////////////////////////////////////
class Snapshot: public LightRefBase<Snapshot> {
public:
Snapshot() { }
Snapshot() {
}
Snapshot(const sp<Snapshot> s): clipRect(s->clipRect), flags(0), previous(s) { }
Snapshot(const sp<Snapshot> s): transform(s->transform), clipRect(s->clipRect),
flags(0), previous(s) {
}
enum Flags {
kFlagClipSet = 0x1,
};
// Local transformations
mat4 transform;
// Clipping rectangle at the time of this snapshot
Rect clipRect;
@@ -45,6 +57,10 @@ public:
sp<Snapshot> previous;
}; // struct Snapshot
///////////////////////////////////////////////////////////////////////////////
// Renderer
///////////////////////////////////////////////////////////////////////////////
class OpenGLRenderer {
public:
OpenGLRenderer();
@@ -58,6 +74,14 @@ public:
void restore();
void restoreToCount(int saveCount);
void translate(float dx, float dy);
void rotate(float degrees);
void scale(float sx, float sy);
void setMatrix(SkMatrix* matrix);
void getMatrix(SkMatrix* matrix);
void concatMatrix(SkMatrix* matrix);
bool clipRect(float left, float top, float right, float bottom);
void drawColor(int color, SkXfermode::Mode mode);
@@ -76,6 +100,8 @@ private:
// Number of saved states
int mSaveCount;
// Base state
Snapshot mFirstSnapshot;
// Current state
sp<Snapshot> mSnapshot;
}; // class OpenGLRenderer