Merge "Move OpenGL support out of ViewRoot into a new HardwareRenderer class."
This commit is contained in:
@@ -65146,7 +65146,7 @@
|
||||
type="android.graphics.Canvas"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
deprecated="deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="gl" type="javax.microedition.khronos.opengles.GL">
|
||||
@@ -66075,7 +66075,7 @@
|
||||
synchronized="false"
|
||||
static="true"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
deprecated="deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
@@ -66132,7 +66132,7 @@
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
deprecated="deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
@@ -66193,6 +66193,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isHardwareAccelerated"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isOpaque"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
@@ -66506,7 +66517,7 @@
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
deprecated="deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="width" type="int">
|
||||
|
||||
341
core/java/android/view/HardwareRenderer.java
Normal file
341
core/java/android/view/HardwareRenderer.java
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* 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 android.view;
|
||||
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.graphics.Canvas;
|
||||
import android.os.SystemClock;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGL11;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLContext;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
import javax.microedition.khronos.egl.EGLSurface;
|
||||
import javax.microedition.khronos.opengles.GL11;
|
||||
|
||||
import static javax.microedition.khronos.opengles.GL10.GL_COLOR_BUFFER_BIT;
|
||||
import static javax.microedition.khronos.opengles.GL10.GL_SCISSOR_TEST;
|
||||
|
||||
/**
|
||||
* Interface for rendering a ViewRoot using hardware acceleration.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
abstract class HardwareRenderer {
|
||||
private boolean mEnabled;
|
||||
private boolean mRequested = true;
|
||||
|
||||
/**
|
||||
* Destroys the hardware rendering context.
|
||||
*/
|
||||
abstract void destroy();
|
||||
|
||||
/**
|
||||
* Initializes the hardware renderer for the specified surface.
|
||||
*
|
||||
* @param holder The holder for the surface to hardware accelerate.
|
||||
*
|
||||
* @return True if the initialization was successful, false otherwise.
|
||||
*/
|
||||
abstract boolean initialize(SurfaceHolder holder);
|
||||
|
||||
/**
|
||||
* Setup the hardware renderer for drawing. This is called for every
|
||||
* frame to draw.
|
||||
*
|
||||
* @param width Width of the drawing surface.
|
||||
* @param height Height of the drawing surface.
|
||||
* @param attachInfo The AttachInfo used to render the ViewRoot.
|
||||
*/
|
||||
abstract void setup(int width, int height, View.AttachInfo attachInfo);
|
||||
|
||||
/**
|
||||
* Draws the specified view.
|
||||
*
|
||||
* @param view The view to draw.
|
||||
* @param attachInfo AttachInfo tied to the specified view.
|
||||
* @param translator Translator used to draw applications in compatibility mode.
|
||||
* @param yoff The vertical offset for the drawing.
|
||||
* @param scalingRequired Whether drawing should be scaled.
|
||||
*/
|
||||
abstract void draw(View view, View.AttachInfo attachInfo,
|
||||
CompatibilityInfo.Translator translator, int yoff, boolean scalingRequired);
|
||||
|
||||
/**
|
||||
* Initializes the hardware renderer for the specified surface and setup the
|
||||
* renderer for drawing, if needed. This is invoked when the ViewRoot has
|
||||
* potentially lost the hardware renderer. The hardware renderer should be
|
||||
* reinitialized and setup when the render {@link #isRequested()} and
|
||||
* {@link #isEnabled()}.
|
||||
*
|
||||
* @param width The width of the drawing surface.
|
||||
* @param height The height of the drawing surface.
|
||||
* @param attachInfo The
|
||||
* @param holder
|
||||
*/
|
||||
void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
|
||||
SurfaceHolder holder) {
|
||||
|
||||
if (isRequested()) {
|
||||
// We lost the gl context, so recreate it.
|
||||
if (!isEnabled()) {
|
||||
if (initialize(holder)) {
|
||||
setup(width, height, attachInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hardware renderer using OpenGL.
|
||||
*
|
||||
* @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.)
|
||||
*
|
||||
* @return A hardware renderer backed by OpenGL.
|
||||
*/
|
||||
static HardwareRenderer createGlRenderer(int glVersion) {
|
||||
switch (glVersion) {
|
||||
case 1:
|
||||
return new Gl10Renderer();
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown GL version: " + glVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether hardware acceleration is currently enabled.
|
||||
*
|
||||
* @return True if hardware acceleration is in use, false otherwise.
|
||||
*/
|
||||
boolean isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether hardware acceleration is currently enabled.
|
||||
*
|
||||
* @param enabled True if the hardware renderer is in use, false otherwise.
|
||||
*/
|
||||
void setEnabled(boolean enabled) {
|
||||
mEnabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether hardware acceleration is currently request but not
|
||||
* necessarily enabled yet.
|
||||
*
|
||||
* @return True if requested, false otherwise.
|
||||
*/
|
||||
boolean isRequested() {
|
||||
return mRequested;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether hardware acceleration is currently request but not
|
||||
* necessarily enabled yet.
|
||||
*
|
||||
* @return True to request hardware acceleration, false otherwise.
|
||||
*/
|
||||
void setRequested(boolean requested) {
|
||||
mRequested = requested;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hardware renderer using OpenGL ES 1.0.
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
static class Gl10Renderer extends HardwareRenderer {
|
||||
private EGL10 mEgl;
|
||||
private EGLDisplay mEglDisplay;
|
||||
private EGLContext mEglContext;
|
||||
private EGLSurface mEglSurface;
|
||||
private GL11 mGL;
|
||||
|
||||
private Canvas mGlCanvas;
|
||||
|
||||
private Gl10Renderer() {
|
||||
}
|
||||
|
||||
private void initializeGL(SurfaceHolder holder) {
|
||||
initializeGLInner(holder);
|
||||
int err = mEgl.eglGetError();
|
||||
if (err != EGL10.EGL_SUCCESS) {
|
||||
destroy();
|
||||
setRequested(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeGLInner(SurfaceHolder holder) {
|
||||
final EGL10 egl = (EGL10) EGLContext.getEGL();
|
||||
mEgl = egl;
|
||||
|
||||
final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
mEglDisplay = eglDisplay;
|
||||
|
||||
int[] version = new int[2];
|
||||
egl.eglInitialize(eglDisplay, version);
|
||||
|
||||
final int[] configSpec = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_DEPTH_SIZE, 0,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
final EGLConfig[] configs = new EGLConfig[1];
|
||||
final int[] numConfig = new int[1];
|
||||
egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig);
|
||||
final EGLConfig config = configs[0];
|
||||
|
||||
/*
|
||||
* Create an OpenGL ES context. This must be done only once, an
|
||||
* OpenGL context is a somewhat heavy object.
|
||||
*/
|
||||
final EGLContext context = egl.eglCreateContext(eglDisplay, config,
|
||||
EGL10.EGL_NO_CONTEXT, null);
|
||||
mEglContext = context;
|
||||
|
||||
/*
|
||||
* Create an EGL surface we can render into.
|
||||
*/
|
||||
EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, holder, null);
|
||||
mEglSurface = surface;
|
||||
|
||||
/*
|
||||
* Before we can issue GL commands, we need to make sure
|
||||
* the context is current and bound to a surface.
|
||||
*/
|
||||
egl.eglMakeCurrent(eglDisplay, surface, surface, context);
|
||||
|
||||
/*
|
||||
* Get to the appropriate GL interface.
|
||||
* This is simply done by casting the GL context to either
|
||||
* GL10 or GL11.
|
||||
*/
|
||||
final GL11 gl = (GL11) context.getGL();
|
||||
mGL = gl;
|
||||
mGlCanvas = new Canvas(gl);
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
void destroy() {
|
||||
if (!isEnabled()) return;
|
||||
|
||||
// inform skia that the context is gone
|
||||
nativeAbandonGlCaches();
|
||||
|
||||
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
|
||||
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
|
||||
mEgl.eglDestroyContext(mEglDisplay, mEglContext);
|
||||
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
|
||||
mEgl.eglTerminate(mEglDisplay);
|
||||
|
||||
mEglContext = null;
|
||||
mEglSurface = null;
|
||||
mEglDisplay = null;
|
||||
mEgl = null;
|
||||
mGlCanvas = null;
|
||||
mGL = null;
|
||||
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
private void checkErrors() {
|
||||
if (isEnabled()) {
|
||||
int err = mEgl.eglGetError();
|
||||
if (err != EGL10.EGL_SUCCESS) {
|
||||
// something bad has happened revert to
|
||||
// normal rendering.
|
||||
destroy();
|
||||
if (err != EGL11.EGL_CONTEXT_LOST) {
|
||||
// we'll try again if it was context lost
|
||||
setRequested(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean initialize(SurfaceHolder holder) {
|
||||
if (isRequested() && !isEnabled()) {
|
||||
initializeGL(holder);
|
||||
return mGlCanvas != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setup(int width, int height, View.AttachInfo attachInfo) {
|
||||
final float scale = attachInfo.mApplicationScale;
|
||||
mGlCanvas.setViewport((int) (width * scale + 0.5f), (int) (height * scale + 0.5f));
|
||||
}
|
||||
|
||||
@Override
|
||||
void draw(View view, View.AttachInfo attachInfo, CompatibilityInfo.Translator translator,
|
||||
int yoff, boolean scalingRequired) {
|
||||
|
||||
Canvas canvas = mGlCanvas;
|
||||
if (mGL != null && canvas != null) {
|
||||
mGL.glDisable(GL_SCISSOR_TEST);
|
||||
mGL.glClearColor(0, 0, 0, 0);
|
||||
mGL.glClear(GL_COLOR_BUFFER_BIT);
|
||||
mGL.glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
|
||||
attachInfo.mIgnoreDirtyState = true;
|
||||
view.mPrivateFlags |= View.DRAWN;
|
||||
|
||||
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
|
||||
try {
|
||||
canvas.translate(0, -yoff);
|
||||
if (translator != null) {
|
||||
translator.translateCanvas(canvas);
|
||||
}
|
||||
canvas.setScreenDensity(scalingRequired ?
|
||||
DisplayMetrics.DENSITY_DEVICE : 0);
|
||||
|
||||
view.draw(canvas);
|
||||
|
||||
} finally {
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
attachInfo.mIgnoreDirtyState = false;
|
||||
|
||||
mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
|
||||
checkErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
|
||||
SurfaceHolder holder) {
|
||||
|
||||
if (isRequested()) {
|
||||
checkErrors();
|
||||
super.initializeIfNeeded(width, height, attachInfo, holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// inform Skia to just abandon its texture cache IDs
|
||||
// doesn't call glDeleteTextures
|
||||
private static native void nativeAbandonGlCaches();
|
||||
}
|
||||
@@ -1566,7 +1566,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
|
||||
boolean scalingRequired = false;
|
||||
Bitmap cache = null;
|
||||
if (canvas.getGL() == null &&
|
||||
if (!canvas.isHardwareAccelerated() &&
|
||||
(flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
|
||||
(flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
|
||||
cache = child.getDrawingCache(true);
|
||||
|
||||
@@ -56,10 +56,6 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.microedition.khronos.egl.*;
|
||||
import javax.microedition.khronos.opengles.*;
|
||||
import static javax.microedition.khronos.opengles.GL10.*;
|
||||
|
||||
/**
|
||||
* The top of a view hierarchy, implementing the needed protocol between View
|
||||
* and the WindowManager. This is for the most part an internal implementation
|
||||
@@ -264,9 +260,8 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
mDensity = context.getResources().getDisplayMetrics().densityDpi;
|
||||
|
||||
// Try to enable hardware acceleration if requested
|
||||
if ((context.getApplicationInfo().flags &
|
||||
ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
|
||||
mHwRenderer = new HardwareRenderer();
|
||||
if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
|
||||
mHwRenderer = HardwareRenderer.createGlRenderer(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,8 +610,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
boolean viewVisibilityChanged = mViewVisibility != viewVisibility
|
||||
|| mNewSurfaceNeeded;
|
||||
|
||||
float appScale = mAttachInfo.mApplicationScale;
|
||||
|
||||
WindowManager.LayoutParams params = null;
|
||||
if (mWindowAttributesChanged) {
|
||||
mWindowAttributesChanged = false;
|
||||
@@ -665,7 +658,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
host.dispatchWindowVisibilityChanged(viewVisibility);
|
||||
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
|
||||
if (mHwRenderer != null) {
|
||||
mHwRenderer.destroyGL();
|
||||
mHwRenderer.destroy();
|
||||
}
|
||||
}
|
||||
if (viewVisibility == View.GONE) {
|
||||
@@ -873,7 +866,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
mPreviousTransparentRegion.setEmpty();
|
||||
|
||||
if (mHwRenderer != null) {
|
||||
hwIntialized = mHwRenderer.initialize();
|
||||
hwIntialized = mHwRenderer.initialize(mHolder);
|
||||
}
|
||||
}
|
||||
} else if (!mSurface.isValid()) {
|
||||
@@ -952,7 +945,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
}
|
||||
|
||||
if (hwIntialized) {
|
||||
mHwRenderer.setup(appScale);
|
||||
mHwRenderer.setup(mWidth, mHeight, mAttachInfo);
|
||||
}
|
||||
|
||||
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
|
||||
@@ -1248,9 +1241,9 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
return;
|
||||
}
|
||||
|
||||
if (mHwRenderer != null && mHwRenderer.mEnabled) {
|
||||
if (mHwRenderer != null && mHwRenderer.isEnabled()) {
|
||||
if (!dirty.isEmpty()) {
|
||||
mHwRenderer.draw(yoff, scalingRequired);
|
||||
mHwRenderer.draw(mView, mAttachInfo, mTranslator, yoff, scalingRequired);
|
||||
}
|
||||
|
||||
if (scrolling) {
|
||||
@@ -1578,7 +1571,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
mAttachInfo.mSurface = null;
|
||||
|
||||
if (mHwRenderer != null) {
|
||||
mHwRenderer.destroyGL();
|
||||
mHwRenderer.destroy();
|
||||
}
|
||||
mSurface.release();
|
||||
|
||||
@@ -1842,7 +1835,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
ensureTouchModeLocally(inTouchMode);
|
||||
|
||||
if (mHwRenderer != null) {
|
||||
mHwRenderer.initializeAndSetup();
|
||||
mHwRenderer.initializeIfNeeded(mWidth, mHeight, mAttachInfo, mHolder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3313,183 +3306,5 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
|
||||
}
|
||||
}
|
||||
|
||||
class HardwareRenderer {
|
||||
private EGL10 mEgl;
|
||||
private EGLDisplay mEglDisplay;
|
||||
private EGLContext mEglContext;
|
||||
private EGLSurface mEglSurface;
|
||||
private GL11 mGL;
|
||||
|
||||
private Canvas mGlCanvas;
|
||||
|
||||
boolean mEnabled;
|
||||
boolean mRequested = true;
|
||||
|
||||
private void initializeGL() {
|
||||
initializeGLInner();
|
||||
int err = mEgl.eglGetError();
|
||||
if (err != EGL10.EGL_SUCCESS) {
|
||||
destroyGL();
|
||||
mRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeGLInner() {
|
||||
final EGL10 egl = (EGL10) EGLContext.getEGL();
|
||||
mEgl = egl;
|
||||
|
||||
final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
mEglDisplay = eglDisplay;
|
||||
|
||||
int[] version = new int[2];
|
||||
egl.eglInitialize(eglDisplay, version);
|
||||
|
||||
final int[] configSpec = {
|
||||
EGL10.EGL_RED_SIZE, 8,
|
||||
EGL10.EGL_GREEN_SIZE, 8,
|
||||
EGL10.EGL_BLUE_SIZE, 8,
|
||||
EGL10.EGL_DEPTH_SIZE, 0,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
final EGLConfig[] configs = new EGLConfig[1];
|
||||
final int[] numConfig = new int[1];
|
||||
egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig);
|
||||
final EGLConfig config = configs[0];
|
||||
|
||||
/*
|
||||
* Create an OpenGL ES context. This must be done only once, an
|
||||
* OpenGL context is a somewhat heavy object.
|
||||
*/
|
||||
final EGLContext context = egl.eglCreateContext(eglDisplay, config,
|
||||
EGL10.EGL_NO_CONTEXT, null);
|
||||
mEglContext = context;
|
||||
|
||||
/*
|
||||
* Create an EGL surface we can render into.
|
||||
*/
|
||||
EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, mHolder, null);
|
||||
mEglSurface = surface;
|
||||
|
||||
/*
|
||||
* Before we can issue GL commands, we need to make sure
|
||||
* the context is current and bound to a surface.
|
||||
*/
|
||||
egl.eglMakeCurrent(eglDisplay, surface, surface, context);
|
||||
|
||||
/*
|
||||
* Get to the appropriate GL interface.
|
||||
* This is simply done by casting the GL context to either
|
||||
* GL10 or GL11.
|
||||
*/
|
||||
final GL11 gl = (GL11) context.getGL();
|
||||
mGL = gl;
|
||||
mGlCanvas = new Canvas(gl);
|
||||
mEnabled = true;
|
||||
}
|
||||
|
||||
void destroyGL() {
|
||||
if (!mEnabled) return;
|
||||
|
||||
// inform skia that the context is gone
|
||||
nativeAbandonGlCaches();
|
||||
|
||||
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
|
||||
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
|
||||
mEgl.eglDestroyContext(mEglDisplay, mEglContext);
|
||||
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
|
||||
mEgl.eglTerminate(mEglDisplay);
|
||||
|
||||
mEglContext = null;
|
||||
mEglSurface = null;
|
||||
mEglDisplay = null;
|
||||
mEgl = null;
|
||||
mGlCanvas = null;
|
||||
mGL = null;
|
||||
|
||||
mEnabled = false;
|
||||
}
|
||||
|
||||
private void checkErrors() {
|
||||
if (mEnabled) {
|
||||
int err = mEgl.eglGetError();
|
||||
if (err != EGL10.EGL_SUCCESS) {
|
||||
// something bad has happened revert to
|
||||
// normal rendering.
|
||||
destroyGL();
|
||||
if (err != EGL11.EGL_CONTEXT_LOST) {
|
||||
// we'll try again if it was context lost
|
||||
mRequested = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean initialize() {
|
||||
if (mRequested && !mEnabled) {
|
||||
initializeGL();
|
||||
return mGlCanvas != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setup(float appScale) {
|
||||
mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f),
|
||||
(int) (mHeight * appScale + 0.5f));
|
||||
}
|
||||
|
||||
void draw(int yoff, boolean scalingRequired) {
|
||||
Canvas canvas = mGlCanvas;
|
||||
if (mGL != null && canvas != null) {
|
||||
mGL.glDisable(GL_SCISSOR_TEST);
|
||||
mGL.glClearColor(0, 0, 0, 0);
|
||||
mGL.glClear(GL_COLOR_BUFFER_BIT);
|
||||
mGL.glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
|
||||
mAttachInfo.mIgnoreDirtyState = true;
|
||||
mView.mPrivateFlags |= View.DRAWN;
|
||||
|
||||
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
|
||||
try {
|
||||
canvas.translate(0, -yoff);
|
||||
if (mTranslator != null) {
|
||||
mTranslator.translateCanvas(canvas);
|
||||
}
|
||||
canvas.setScreenDensity(scalingRequired ?
|
||||
DisplayMetrics.DENSITY_DEVICE : 0);
|
||||
|
||||
mView.draw(canvas);
|
||||
|
||||
} finally {
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
mAttachInfo.mIgnoreDirtyState = false;
|
||||
|
||||
mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
|
||||
checkErrors();
|
||||
}
|
||||
}
|
||||
|
||||
void initializeAndSetup() {
|
||||
if (mRequested) {
|
||||
checkErrors();
|
||||
// we lost the gl context, so recreate it.
|
||||
if (mRequested && !mEnabled) {
|
||||
initializeGL();
|
||||
if (mGlCanvas != null) {
|
||||
float appScale = mAttachInfo.mApplicationScale;
|
||||
mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f),
|
||||
(int) (mHeight * appScale + 0.5f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static native void nativeShowFPS(Canvas canvas, int durationMillis);
|
||||
|
||||
// inform skia to just abandon its texture cache IDs
|
||||
// doesn't call glDeleteTextures
|
||||
private static native void nativeAbandonGlCaches();
|
||||
}
|
||||
|
||||
@@ -131,7 +131,8 @@ LOCAL_SRC_FILES:= \
|
||||
android_backup_BackupDataInput.cpp \
|
||||
android_backup_BackupDataOutput.cpp \
|
||||
android_backup_FileBackupHelperBase.cpp \
|
||||
android_backup_BackupHelperDispatcher.cpp
|
||||
android_backup_BackupHelperDispatcher.cpp \
|
||||
android_view_HardwareRenderer.cpp \
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(JNI_H_INCLUDE) \
|
||||
|
||||
46
core/jni/android_view_HardwareRenderer.cpp
Normal file
46
core/jni/android_view_HardwareRenderer.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <utils/SkGLCanvas.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <utils/misc.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
static void android_view_HardwareRenderer_abandonGlCaches(JNIEnv* env, jobject) {
|
||||
SkGLCanvas::AbandonAllTextures();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const char* const kClassPathName = "android/view/HardwareRenderer";
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{ "nativeAbandonGlCaches", "()V",
|
||||
(void*)android_view_HardwareRenderer_abandonGlCaches },
|
||||
};
|
||||
|
||||
int register_android_view_HardwareRenderer(JNIEnv* env) {
|
||||
return AndroidRuntime::registerNativeMethods(env,
|
||||
kClassPathName, gMethods, NELEM(gMethods));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -76,10 +76,6 @@ static void android_view_ViewRoot_showFPS(JNIEnv* env, jobject, jobject jcanvas,
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
static void android_view_ViewRoot_abandonGlCaches(JNIEnv* env, jobject) {
|
||||
SkGLCanvas::AbandonAllTextures();
|
||||
}
|
||||
|
||||
static jintArray android_view_ViewRoot_makeInputChannel(JNIEnv* env, jobject) {
|
||||
int fd[2];
|
||||
jint* arrayData = NULL;
|
||||
@@ -120,8 +116,6 @@ const char* const kClassPathName = "android/view/ViewRoot";
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{ "nativeShowFPS", "(Landroid/graphics/Canvas;I)V",
|
||||
(void*)android_view_ViewRoot_showFPS },
|
||||
{ "nativeAbandonGlCaches", "()V",
|
||||
(void*)android_view_ViewRoot_abandonGlCaches },
|
||||
{ "makeInputChannel", "()[I",
|
||||
(void*)android_view_ViewRoot_makeInputChannel }
|
||||
};
|
||||
|
||||
@@ -117,16 +117,33 @@ public class Canvas {
|
||||
*
|
||||
* <p>The initial target density of the canvas is the same as the initial
|
||||
* density of bitmaps as per {@link Bitmap#getDensity() Bitmap.getDensity()}.
|
||||
*
|
||||
* @deprecated This constructor is not supported and should not be invoked.
|
||||
*/
|
||||
public Canvas(GL gl) {
|
||||
mNativeCanvas = initGL();
|
||||
mGL = gl;
|
||||
mDensity = Bitmap.getDefaultDensity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this Canvas uses hardware acceleration.
|
||||
*
|
||||
* Note that this method does not define what type of hardware acceleration
|
||||
* may or may not be used.
|
||||
*
|
||||
* @return True if drawing operations are hardware accelerated,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean isHardwareAccelerated() {
|
||||
return mGL != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the GL object associated with this canvas, or null if it is not
|
||||
* backed by GL.
|
||||
*
|
||||
* @deprecated This method is not supported and should not be invoked.
|
||||
*/
|
||||
public GL getGL() {
|
||||
return mGL;
|
||||
@@ -136,6 +153,8 @@ public class Canvas {
|
||||
* Call this to free up OpenGL resources that may be cached or allocated
|
||||
* on behalf of the Canvas. Any subsequent drawing with a GL-backed Canvas
|
||||
* will have to recreate those resources.
|
||||
*
|
||||
* @deprecated This method is not supported and should not be invoked.
|
||||
*/
|
||||
public static void freeGlCaches() {
|
||||
freeCaches();
|
||||
@@ -168,8 +187,10 @@ public class Canvas {
|
||||
* Set the viewport dimensions if this canvas is GL based. If it is not,
|
||||
* this method is ignored and no exception is thrown.
|
||||
*
|
||||
* @param width The width of the viewport
|
||||
* @param height The height of the viewport
|
||||
* @param width The width of the viewport
|
||||
* @param height The height of the viewport
|
||||
*
|
||||
* @deprecated This method is not supported and should not be invoked.
|
||||
*/
|
||||
public void setViewport(int width, int height) {
|
||||
if (mGL != null) {
|
||||
@@ -1339,8 +1360,8 @@ public class Canvas {
|
||||
* position (start + length) can be used for shaping context.
|
||||
* @param x the x position at which to draw the text
|
||||
* @param y the y position at which to draw the text
|
||||
* @param dir the run direction, either {@link DIRECTION_LTR} or
|
||||
* {@link DIRECTION_RTL}.
|
||||
* @param dir the run direction, either {@link #DIRECTION_LTR} or
|
||||
* {@link #DIRECTION_RTL}.
|
||||
* @param paint the paint
|
||||
* @hide
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user