Loading api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -22039,9 +22039,12 @@ package android.view { method public android.graphics.SurfaceTexture getSurfaceTexture(); method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener(); method public boolean isAvailable(); method public android.graphics.Canvas lockCanvas(); method public android.graphics.Canvas lockCanvas(android.graphics.Rect); method protected final void onDraw(android.graphics.Canvas); method public void setOpaque(boolean); method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener); method public void unlockCanvasAndPost(android.graphics.Canvas); } public static abstract interface TextureView.SurfaceTextureListener { core/java/android/view/TextureView.java +94 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.util.AttributeSet; import android.util.Log; Loading Loading @@ -107,6 +108,14 @@ public class TextureView extends View { private SurfaceTexture.OnFrameAvailableListener mUpdateListener; private Canvas mCanvas; private int mSaveCount; private final Object[] mNativeWindowLock = new Object[0]; // Used from native code, do not write! @SuppressWarnings({"UnusedDeclaration"}) private int mNativeWindow; /** * Creates a new TextureView. * Loading Loading @@ -190,6 +199,10 @@ public class TextureView extends View { mListener.onSurfaceTextureDestroyed(mSurface); } synchronized (mNativeWindowLock) { nDestroyNativeWindow(); } mLayer.destroy(); mSurface = null; mLayer = null; Loading Loading @@ -274,6 +287,7 @@ public class TextureView extends View { mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque); mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer); nSetDefaultBufferSize(mSurface, getWidth(), getHeight()); nCreateNativeWindow(mSurface); mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() { @Override Loading Loading @@ -430,6 +444,79 @@ public class TextureView extends View { return mSurface != null; } /** * <p>Start editing the pixels in the surface. The returned Canvas can be used * to draw into the surface's bitmap. A null is returned if the surface has * not been created or otherwise cannot be edited. You will usually need * to implement * {@link SurfaceTextureListener#onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int)} * to find out when the Surface is available for use.</p> * * <p>The content of the Surface is never preserved between unlockCanvas() * and lockCanvas(), for this reason, every pixel within the Surface area * must be written. The only exception to this rule is when a dirty * rectangle is specified, in which case, non-dirty pixels will be * preserved.</p> * * @return A Canvas used to draw into the surface. * * @see #lockCanvas(android.graphics.Rect) * @see #unlockCanvasAndPost(android.graphics.Canvas) */ public Canvas lockCanvas() { return lockCanvas(null); } /** * Just like {@link #lockCanvas()} but allows specification of a dirty * rectangle. Every pixel within that rectangle must be written; however * pixels outside the dirty rectangle will be preserved by the next call * to lockCanvas(). * * @param dirty Area of the surface that will be modified. * @return A Canvas used to draw into the surface. * * @see #lockCanvas() * @see #unlockCanvasAndPost(android.graphics.Canvas) */ public Canvas lockCanvas(Rect dirty) { if (!isAvailable()) return null; if (mCanvas == null) { mCanvas = new Canvas(); } synchronized (mNativeWindowLock) { nLockCanvas(mNativeWindow, mCanvas, dirty); } mSaveCount = mCanvas.save(); return mCanvas; } /** * Finish editing pixels in the surface. After this call, the surface's * current pixels will be shown on the screen, but its content is lost, * in particular there is no guarantee that the content of the Surface * will remain unchanged when lockCanvas() is called again. * * @param canvas The Canvas previously returned by lockCanvas() * * @see #lockCanvas() * @see #lockCanvas(android.graphics.Rect) */ public void unlockCanvasAndPost(Canvas canvas) { if (mCanvas != null && canvas == mCanvas) { canvas.restoreToCount(mSaveCount); mSaveCount = 0; synchronized (mNativeWindowLock) { nUnlockCanvasAndPost(mNativeWindow, mCanvas); } } } /** * Returns the {@link SurfaceTexture} used by this view. This method * may return null if the view is not attached to a window or if the surface Loading Loading @@ -506,6 +593,12 @@ public class TextureView extends View { public void onSurfaceTextureUpdated(SurfaceTexture surface); } private native void nCreateNativeWindow(SurfaceTexture surface); private native void nDestroyNativeWindow(); private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture, int width, int height); private static native void nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty); private static native void nUnlockCanvasAndPost(int nativeWindow, Canvas canvas); } core/jni/android_view_GLES20Canvas.cpp +2 −4 Original line number Diff line number Diff line Loading @@ -859,10 +859,8 @@ int register_android_view_GLES20Canvas(JNIEnv* env) { const char* const kActivityThreadPathName = "android/app/ActivityThread"; int register_android_app_ActivityThread(JNIEnv* env) { return AndroidRuntime::registerNativeMethods( env, kActivityThreadPathName, int register_android_app_ActivityThread(JNIEnv* env) { return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName, gActivityThreadMethods, NELEM(gActivityThreadMethods)); } Loading core/jni/android_view_TextureView.cpp +187 −1 Original line number Diff line number Diff line Loading @@ -19,10 +19,47 @@ #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_graphics_SurfaceTexture.h> #include <ui/Region.h> #include <ui/Rect.h> #include <gui/SurfaceTexture.h> #include <gui/SurfaceTextureClient.h> #include <SkBitmap.h> #include <SkCanvas.h> namespace android { // ---------------------------------------------------------------------------- // JNI Glue // ---------------------------------------------------------------------------- static struct { jmethodID set; jfieldID left; jfieldID top; jfieldID right; jfieldID bottom; } gRectClassInfo; static struct { jfieldID nativeCanvas; jfieldID surfaceFormat; } gCanvasClassInfo; static struct { jfieldID nativeWindow; } gTextureViewClassInfo; #define GET_INT(object, field) \ env->GetIntField(object, field) #define SET_INT(object, field, value) \ env->SetIntField(object, field, value) #define INVOKEV(object, method, ...) \ env->CallVoidMethod(object, method, __VA_ARGS__) // ---------------------------------------------------------------------------- // Native layer // ---------------------------------------------------------------------------- Loading @@ -34,6 +71,118 @@ static void android_view_TextureView_setDefaultBufferSize(JNIEnv* env, jobject, surfaceTexture->setDefaultBufferSize(width, height); } static inline SkBitmap::Config convertPixelFormat(int32_t format) { switch (format) { case WINDOW_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; case WINDOW_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; case WINDOW_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; default: return SkBitmap::kNo_Config; } } /** * This is a private API, and this implementation is also provided in the NDK. * However, the NDK links against android_runtime, which means that using the * NDK implementation would create a circular dependency between the libraries. */ static int32_t native_window_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, Rect* inOutDirtyBounds) { return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds); } static int32_t native_window_unlockAndPost(ANativeWindow* window) { return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST); } static void android_view_TextureView_createNativeWindow(JNIEnv* env, jobject textureView, jobject surface) { sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface)); sp<ANativeWindow> window = new SurfaceTextureClient(surfaceTexture); window->incStrong(0); SET_INT(textureView, gTextureViewClassInfo.nativeWindow, jint(window.get())); } static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject textureView) { ANativeWindow* nativeWindow = (ANativeWindow*) GET_INT(textureView, gTextureViewClassInfo.nativeWindow); if (nativeWindow) { sp<ANativeWindow> window(nativeWindow); window->decStrong(0); SET_INT(textureView, gTextureViewClassInfo.nativeWindow, 0); } } static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject, jint nativeWindow, jobject canvas, jobject dirtyRect) { if (!nativeWindow) { return; } ANativeWindow_Buffer buffer; Rect rect; if (dirtyRect) { rect.left = GET_INT(dirtyRect, gRectClassInfo.left); rect.top = GET_INT(dirtyRect, gRectClassInfo.top); rect.right = GET_INT(dirtyRect, gRectClassInfo.right); rect.bottom = GET_INT(dirtyRect, gRectClassInfo.bottom); } else { rect.set(Rect(0x3FFF, 0x3FFF)); } sp<ANativeWindow> window((ANativeWindow*) nativeWindow); native_window_lock(window.get(), &buffer, &rect); ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format); SkBitmap bitmap; bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount); if (buffer.format == WINDOW_FORMAT_RGBX_8888) { bitmap.setIsOpaque(true); } if (buffer.width > 0 && buffer.height > 0) { bitmap.setPixels(buffer.bits); } else { bitmap.setPixels(NULL); } SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format); SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); nativeCanvas->setBitmapDevice(bitmap); SkRect clipRect; clipRect.set(rect.left, rect.top, rect.right, rect.bottom); nativeCanvas->clipRect(clipRect); if (dirtyRect) { INVOKEV(dirtyRect, gRectClassInfo.set, int(rect.left), int(rect.top), int(rect.right), int(rect.bottom)); } } static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, jint nativeWindow, jobject canvas) { SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); nativeCanvas->setBitmapDevice(SkBitmap()); if (nativeWindow) { sp<ANativeWindow> window((ANativeWindow*) nativeWindow); native_window_unlockAndPost(window.get()); } } // ---------------------------------------------------------------------------- // JNI Glue // ---------------------------------------------------------------------------- Loading @@ -42,10 +191,47 @@ const char* const kClassPathName = "android/view/TextureView"; static JNINativeMethod gMethods[] = { { "nSetDefaultBufferSize", "(Landroid/graphics/SurfaceTexture;II)V", (void*) android_view_TextureView_setDefaultBufferSize } (void*) android_view_TextureView_setDefaultBufferSize }, { "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V", (void*) android_view_TextureView_createNativeWindow }, { "nDestroyNativeWindow", "()V", (void*) android_view_TextureView_destroyNativeWindow }, { "nLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V", (void*) android_view_TextureView_lockCanvas }, { "nUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V", (void*) android_view_TextureView_unlockCanvasAndPost }, }; #define FIND_CLASS(var, className) \ var = env->FindClass(className); \ LOG_FATAL_IF(!var, "Unable to find class " className); #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ var = env->GetMethodID(clazz, methodName, methodDescriptor); \ LOG_FATAL_IF(!var, "Unable to find method " methodName); #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ LOG_FATAL_IF(!var, "Unable to find field" fieldName); int register_android_view_TextureView(JNIEnv* env) { jclass clazz; FIND_CLASS(clazz, "android/graphics/Rect"); GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V"); GET_FIELD_ID(gRectClassInfo.left, clazz, "left", "I"); GET_FIELD_ID(gRectClassInfo.top, clazz, "top", "I"); GET_FIELD_ID(gRectClassInfo.right, clazz, "right", "I"); GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I"); FIND_CLASS(clazz, "android/graphics/Canvas"); GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I"); GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I"); FIND_CLASS(clazz, "android/view/TextureView"); GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I"); return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } Loading tests/HwAccelerationTest/AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,15 @@ </intent-filter> </activity> <activity android:name="CanvasTextureViewActivity" android:label="_CanvasTextureView"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="GLTextureViewActivity" android:label="_TextureViewGL"> Loading Loading
api/current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -22039,9 +22039,12 @@ package android.view { method public android.graphics.SurfaceTexture getSurfaceTexture(); method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener(); method public boolean isAvailable(); method public android.graphics.Canvas lockCanvas(); method public android.graphics.Canvas lockCanvas(android.graphics.Rect); method protected final void onDraw(android.graphics.Canvas); method public void setOpaque(boolean); method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener); method public void unlockCanvasAndPost(android.graphics.Canvas); } public static abstract interface TextureView.SurfaceTextureListener {
core/java/android/view/TextureView.java +94 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.util.AttributeSet; import android.util.Log; Loading Loading @@ -107,6 +108,14 @@ public class TextureView extends View { private SurfaceTexture.OnFrameAvailableListener mUpdateListener; private Canvas mCanvas; private int mSaveCount; private final Object[] mNativeWindowLock = new Object[0]; // Used from native code, do not write! @SuppressWarnings({"UnusedDeclaration"}) private int mNativeWindow; /** * Creates a new TextureView. * Loading Loading @@ -190,6 +199,10 @@ public class TextureView extends View { mListener.onSurfaceTextureDestroyed(mSurface); } synchronized (mNativeWindowLock) { nDestroyNativeWindow(); } mLayer.destroy(); mSurface = null; mLayer = null; Loading Loading @@ -274,6 +287,7 @@ public class TextureView extends View { mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque); mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer); nSetDefaultBufferSize(mSurface, getWidth(), getHeight()); nCreateNativeWindow(mSurface); mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() { @Override Loading Loading @@ -430,6 +444,79 @@ public class TextureView extends View { return mSurface != null; } /** * <p>Start editing the pixels in the surface. The returned Canvas can be used * to draw into the surface's bitmap. A null is returned if the surface has * not been created or otherwise cannot be edited. You will usually need * to implement * {@link SurfaceTextureListener#onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int)} * to find out when the Surface is available for use.</p> * * <p>The content of the Surface is never preserved between unlockCanvas() * and lockCanvas(), for this reason, every pixel within the Surface area * must be written. The only exception to this rule is when a dirty * rectangle is specified, in which case, non-dirty pixels will be * preserved.</p> * * @return A Canvas used to draw into the surface. * * @see #lockCanvas(android.graphics.Rect) * @see #unlockCanvasAndPost(android.graphics.Canvas) */ public Canvas lockCanvas() { return lockCanvas(null); } /** * Just like {@link #lockCanvas()} but allows specification of a dirty * rectangle. Every pixel within that rectangle must be written; however * pixels outside the dirty rectangle will be preserved by the next call * to lockCanvas(). * * @param dirty Area of the surface that will be modified. * @return A Canvas used to draw into the surface. * * @see #lockCanvas() * @see #unlockCanvasAndPost(android.graphics.Canvas) */ public Canvas lockCanvas(Rect dirty) { if (!isAvailable()) return null; if (mCanvas == null) { mCanvas = new Canvas(); } synchronized (mNativeWindowLock) { nLockCanvas(mNativeWindow, mCanvas, dirty); } mSaveCount = mCanvas.save(); return mCanvas; } /** * Finish editing pixels in the surface. After this call, the surface's * current pixels will be shown on the screen, but its content is lost, * in particular there is no guarantee that the content of the Surface * will remain unchanged when lockCanvas() is called again. * * @param canvas The Canvas previously returned by lockCanvas() * * @see #lockCanvas() * @see #lockCanvas(android.graphics.Rect) */ public void unlockCanvasAndPost(Canvas canvas) { if (mCanvas != null && canvas == mCanvas) { canvas.restoreToCount(mSaveCount); mSaveCount = 0; synchronized (mNativeWindowLock) { nUnlockCanvasAndPost(mNativeWindow, mCanvas); } } } /** * Returns the {@link SurfaceTexture} used by this view. This method * may return null if the view is not attached to a window or if the surface Loading Loading @@ -506,6 +593,12 @@ public class TextureView extends View { public void onSurfaceTextureUpdated(SurfaceTexture surface); } private native void nCreateNativeWindow(SurfaceTexture surface); private native void nDestroyNativeWindow(); private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture, int width, int height); private static native void nLockCanvas(int nativeWindow, Canvas canvas, Rect dirty); private static native void nUnlockCanvasAndPost(int nativeWindow, Canvas canvas); }
core/jni/android_view_GLES20Canvas.cpp +2 −4 Original line number Diff line number Diff line Loading @@ -859,10 +859,8 @@ int register_android_view_GLES20Canvas(JNIEnv* env) { const char* const kActivityThreadPathName = "android/app/ActivityThread"; int register_android_app_ActivityThread(JNIEnv* env) { return AndroidRuntime::registerNativeMethods( env, kActivityThreadPathName, int register_android_app_ActivityThread(JNIEnv* env) { return AndroidRuntime::registerNativeMethods(env, kActivityThreadPathName, gActivityThreadMethods, NELEM(gActivityThreadMethods)); } Loading
core/jni/android_view_TextureView.cpp +187 −1 Original line number Diff line number Diff line Loading @@ -19,10 +19,47 @@ #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_graphics_SurfaceTexture.h> #include <ui/Region.h> #include <ui/Rect.h> #include <gui/SurfaceTexture.h> #include <gui/SurfaceTextureClient.h> #include <SkBitmap.h> #include <SkCanvas.h> namespace android { // ---------------------------------------------------------------------------- // JNI Glue // ---------------------------------------------------------------------------- static struct { jmethodID set; jfieldID left; jfieldID top; jfieldID right; jfieldID bottom; } gRectClassInfo; static struct { jfieldID nativeCanvas; jfieldID surfaceFormat; } gCanvasClassInfo; static struct { jfieldID nativeWindow; } gTextureViewClassInfo; #define GET_INT(object, field) \ env->GetIntField(object, field) #define SET_INT(object, field, value) \ env->SetIntField(object, field, value) #define INVOKEV(object, method, ...) \ env->CallVoidMethod(object, method, __VA_ARGS__) // ---------------------------------------------------------------------------- // Native layer // ---------------------------------------------------------------------------- Loading @@ -34,6 +71,118 @@ static void android_view_TextureView_setDefaultBufferSize(JNIEnv* env, jobject, surfaceTexture->setDefaultBufferSize(width, height); } static inline SkBitmap::Config convertPixelFormat(int32_t format) { switch (format) { case WINDOW_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; case WINDOW_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; case WINDOW_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; default: return SkBitmap::kNo_Config; } } /** * This is a private API, and this implementation is also provided in the NDK. * However, the NDK links against android_runtime, which means that using the * NDK implementation would create a circular dependency between the libraries. */ static int32_t native_window_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, Rect* inOutDirtyBounds) { return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds); } static int32_t native_window_unlockAndPost(ANativeWindow* window) { return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST); } static void android_view_TextureView_createNativeWindow(JNIEnv* env, jobject textureView, jobject surface) { sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface)); sp<ANativeWindow> window = new SurfaceTextureClient(surfaceTexture); window->incStrong(0); SET_INT(textureView, gTextureViewClassInfo.nativeWindow, jint(window.get())); } static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject textureView) { ANativeWindow* nativeWindow = (ANativeWindow*) GET_INT(textureView, gTextureViewClassInfo.nativeWindow); if (nativeWindow) { sp<ANativeWindow> window(nativeWindow); window->decStrong(0); SET_INT(textureView, gTextureViewClassInfo.nativeWindow, 0); } } static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject, jint nativeWindow, jobject canvas, jobject dirtyRect) { if (!nativeWindow) { return; } ANativeWindow_Buffer buffer; Rect rect; if (dirtyRect) { rect.left = GET_INT(dirtyRect, gRectClassInfo.left); rect.top = GET_INT(dirtyRect, gRectClassInfo.top); rect.right = GET_INT(dirtyRect, gRectClassInfo.right); rect.bottom = GET_INT(dirtyRect, gRectClassInfo.bottom); } else { rect.set(Rect(0x3FFF, 0x3FFF)); } sp<ANativeWindow> window((ANativeWindow*) nativeWindow); native_window_lock(window.get(), &buffer, &rect); ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format); SkBitmap bitmap; bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount); if (buffer.format == WINDOW_FORMAT_RGBX_8888) { bitmap.setIsOpaque(true); } if (buffer.width > 0 && buffer.height > 0) { bitmap.setPixels(buffer.bits); } else { bitmap.setPixels(NULL); } SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format); SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); nativeCanvas->setBitmapDevice(bitmap); SkRect clipRect; clipRect.set(rect.left, rect.top, rect.right, rect.bottom); nativeCanvas->clipRect(clipRect); if (dirtyRect) { INVOKEV(dirtyRect, gRectClassInfo.set, int(rect.left), int(rect.top), int(rect.right), int(rect.bottom)); } } static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, jint nativeWindow, jobject canvas) { SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas); nativeCanvas->setBitmapDevice(SkBitmap()); if (nativeWindow) { sp<ANativeWindow> window((ANativeWindow*) nativeWindow); native_window_unlockAndPost(window.get()); } } // ---------------------------------------------------------------------------- // JNI Glue // ---------------------------------------------------------------------------- Loading @@ -42,10 +191,47 @@ const char* const kClassPathName = "android/view/TextureView"; static JNINativeMethod gMethods[] = { { "nSetDefaultBufferSize", "(Landroid/graphics/SurfaceTexture;II)V", (void*) android_view_TextureView_setDefaultBufferSize } (void*) android_view_TextureView_setDefaultBufferSize }, { "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V", (void*) android_view_TextureView_createNativeWindow }, { "nDestroyNativeWindow", "()V", (void*) android_view_TextureView_destroyNativeWindow }, { "nLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V", (void*) android_view_TextureView_lockCanvas }, { "nUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V", (void*) android_view_TextureView_unlockCanvasAndPost }, }; #define FIND_CLASS(var, className) \ var = env->FindClass(className); \ LOG_FATAL_IF(!var, "Unable to find class " className); #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ var = env->GetMethodID(clazz, methodName, methodDescriptor); \ LOG_FATAL_IF(!var, "Unable to find method " methodName); #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ LOG_FATAL_IF(!var, "Unable to find field" fieldName); int register_android_view_TextureView(JNIEnv* env) { jclass clazz; FIND_CLASS(clazz, "android/graphics/Rect"); GET_METHOD_ID(gRectClassInfo.set, clazz, "set", "(IIII)V"); GET_FIELD_ID(gRectClassInfo.left, clazz, "left", "I"); GET_FIELD_ID(gRectClassInfo.top, clazz, "top", "I"); GET_FIELD_ID(gRectClassInfo.right, clazz, "right", "I"); GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I"); FIND_CLASS(clazz, "android/graphics/Canvas"); GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I"); GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I"); FIND_CLASS(clazz, "android/view/TextureView"); GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I"); return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } Loading
tests/HwAccelerationTest/AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,15 @@ </intent-filter> </activity> <activity android:name="CanvasTextureViewActivity" android:label="_CanvasTextureView"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="GLTextureViewActivity" android:label="_TextureViewGL"> Loading