Support MSAA4 and (non-ES) OpenGL in Android SampleApp

Add a menu item to set the OpenGL context type that SampleApp uses on
Android. The submenu of the new item will present options to create
OpenGL ES or OpenGL, aliased or multisampled.

R=djsollen@google.com, bsalomon@google.com

Author: kkinnunen@nvidia.com

Review URL: https://codereview.chromium.org/60273006

git-svn-id: http://skia.googlecode.com/svn/trunk@12610 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-12-10 20:37:41 +00:00
Родитель bc55eec80e
Коммит a3b84d41ef
8 изменённых файлов: 293 добавлений и 23 удалений

Просмотреть файл

@ -29,12 +29,7 @@ public:
int fStencilBits;
};
bool attach(SkBackEndTypes /* attachType */, int /* msaaSampleCount */, AttachmentInfo* info) {
// These are the values requested in SkiaSampleView.java
info->fSampleCount = 0;
info->fStencilBits = 8;
return true;
}
bool attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo* info);
void detach() {}
void present() {}

Просмотреть файл

@ -44,11 +44,13 @@ struct WindowGlue {
jmethodID m_inval;
jmethodID m_queueSkEvent;
jmethodID m_startTimer;
jmethodID m_getMSAASampleCount;
WindowGlue() {
m_obj = NULL;
m_inval = NULL;
m_queueSkEvent = NULL;
m_startTimer = NULL;
m_getMSAASampleCount = NULL;
}
} gWindowGlue;
@ -58,6 +60,23 @@ SampleWindow* gWindow;
///////////// SkOSWindow impl /////////////
///////////////////////////////////////////
bool SkOSWindow::attach(SkBackEndTypes /* attachType */, int /*msaaSampleCount*/, AttachmentInfo* info)
{
JNIEnv* env = gActivityGlue.m_env;
if (!env || !gWindowGlue.m_getMSAASampleCount || !gWindowGlue.m_obj) {
return false;
}
if (env->IsSameObject(gWindowGlue.m_obj, NULL)) {
SkDebugf("ERROR: The JNI WeakRef to the Window is invalid");
return false;
}
info->fSampleCount = env->CallIntMethod(gWindowGlue.m_obj, gWindowGlue.m_getMSAASampleCount);
// This is the value requested in SkiaSampleView.java.
info->fStencilBits = 8;
return true;
}
void SkOSWindow::onSetTitle(const char title[])
{
JNIEnv* env = gActivityGlue.m_env;
@ -155,7 +174,7 @@ static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[],
}
JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env,
jobject thiz, jobject jsampleActivity)
jobject thiz, jobject jsampleActivity, jint msaaSampleCount)
{
// setup jni hooks to the java activity
gActivityGlue.m_env = env;
@ -173,12 +192,25 @@ JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env,
gWindowGlue.m_inval = GetJMethod(env, clazz, "requestRender", "()V");
gWindowGlue.m_queueSkEvent = GetJMethod(env, clazz, "queueSkEvent", "()V");
gWindowGlue.m_startTimer = GetJMethod(env, clazz, "startTimer", "(I)V");
gWindowGlue.m_getMSAASampleCount = GetJMethod(env, clazz, "getMSAASampleCount", "()I");
env->DeleteLocalRef(clazz);
application_init();
SkTArray<const char*> args;
args.push_back("SampleApp");
// TODO: push ability to select skp dir into the UI
const char* argv[] = { "SampleApp", "--pictureDir", "/sdcard/skiabot/skia_skp" };
gWindow = new SampleWindow(NULL, sizeof(argv)/sizeof(char*), const_cast<char**>(argv), NULL);
args.push_back("--pictureDir");
args.push_back("/sdcard/skiabot/skia_skp");
SkString msaaSampleCountString;
if (msaaSampleCount > 0) {
args.push_back("--msaa");
msaaSampleCountString.appendS32(static_cast<uint32_t>(msaaSampleCount));
args.push_back(msaaSampleCountString.c_str());
}
gWindow = new SampleWindow(NULL, args.count(), const_cast<char**>(args.begin()), NULL);
// send the list of slides up to the activity
const int slideCount = gWindow->sampleCount();

Просмотреть файл

@ -10,10 +10,10 @@ extern "C" {
/*
* Class: com_skia_SkiaSampleRenderer
* Method: init
* Signature: (Lcom/skia/SkiaSampleActivity;)V
* Signature: (Lcom/skia/SkiaSampleActivity;I)V
*/
JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init
(JNIEnv *, jobject, jobject);
(JNIEnv *, jobject, jobject, jint);
/*
* Class: com_skia_SkiaSampleRenderer

Просмотреть файл

@ -42,6 +42,32 @@
android:id="@+id/bbox"
android:title="@string/bbox"
/>
<item
android:id="@+id/glcontext_menu"
android:title="@string/glcontext_menu">
<menu>
<item
android:id="@+id/glcontext_opengles"
android:title="@string/glcontext_opengles"
android:checkable="true"
/>
<item
android:id="@+id/glcontext_msaa4_opengles"
android:title="@string/glcontext_msaa4_opengles"
android:checkable="true"
/>
<item
android:id="@+id/glcontext_opengl"
android:title="@string/glcontext_opengl"
android:checkable="true"
/>
<item
android:id="@+id/glcontext_msaa4_opengl"
android:title="@string/glcontext_msaa4_opengl"
android:checkable="true"
/>
</menu>
</item>
<item
android:id="@+id/save_to_pdf"
android:title="@string/save_to_pdf"

Просмотреть файл

@ -10,4 +10,9 @@
<string name="save_to_pdf">Save to PDF</string>
<string name="save_failed">Save Failed</string>
<string name="file_saved">%s saved!</string>
<string name="glcontext_menu">Set OpenGL Context Type</string>
<string name="glcontext_opengles">OpenGL ES</string>
<string name="glcontext_msaa4_opengles">OpenGL ES, MSAA4</string>
<string name="glcontext_opengl">OpenGL</string>
<string name="glcontext_msaa4_opengl">OpenGL, MSAA4</string>
</resources>

Просмотреть файл

@ -11,6 +11,7 @@ import android.app.ActionBar;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@ -38,7 +39,6 @@ public class SkiaSampleActivity extends Activity
setContentView(R.layout.layout);
mTitle = (TextView) findViewById(R.id.title_view);
mSampleView = new SkiaSampleView(this);
mSlideList = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1);
try {
@ -50,18 +50,28 @@ public class SkiaSampleActivity extends Activity
try {
System.loadLibrary("SampleApp");
LinearLayout holder = (LinearLayout) findViewById(R.id.holder);
holder.addView(mSampleView, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
createSampleView(false, 0);
setupActionBar();
} catch (UnsatisfiedLinkError e) {
mTitle.setText("ERROR: native library could not be loaded");
}
}
private void createSampleView(boolean useOpenGLAPI, int msaaSampleCount) {
if (mSampleView != null) {
ViewGroup viewGroup = (ViewGroup) mSampleView.getParent();
viewGroup.removeView(mSampleView);
mSampleView.terminate();
}
mSampleView = new SkiaSampleView(this, useOpenGLAPI, msaaSampleCount);
LinearLayout holder = (LinearLayout) findViewById(R.id.holder);
holder.addView(mSampleView, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
}
private void setupActionBar() {
ActionBar.OnNavigationListener navigationCallback = new ActionBar.OnNavigationListener() {
@Override
@ -81,7 +91,7 @@ public class SkiaSampleActivity extends Activity
@Override
protected void onResume () {
super.onResume();
if (mSampleView.getWidth() > 0 && mSampleView.getHeight() > 0) {
if (mSampleView != null && mSampleView.getWidth() > 0 && mSampleView.getHeight() > 0) {
//TODO try mSampleView.requestRender() instead
mSampleView.inval();
}
@ -89,7 +99,9 @@ public class SkiaSampleActivity extends Activity
@Override
public void onDestroy() {
mSampleView.terminate();
if (mSampleView != null) {
mSampleView.terminate();
}
super.onDestroy();
}
@ -99,8 +111,39 @@ public class SkiaSampleActivity extends Activity
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mSampleView != null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
((MenuItem) menu.findItem(R.id.glcontext_menu))
.setEnabled(false);
} else {
boolean usesOpenGLAPI = mSampleView.getUsesOpenGLAPI();
boolean isMSAA4 = mSampleView.getMSAASampleCount() == 4;
((MenuItem) menu.findItem(R.id.glcontext_opengles))
.setChecked(!usesOpenGLAPI && !isMSAA4);
((MenuItem) menu.findItem(R.id.glcontext_msaa4_opengles))
.setChecked(!usesOpenGLAPI && isMSAA4);
((MenuItem) menu.findItem(R.id.glcontext_opengl))
.setChecked(usesOpenGLAPI && !isMSAA4);
((MenuItem) menu.findItem(R.id.glcontext_msaa4_opengl))
.setChecked(usesOpenGLAPI && isMSAA4);
}
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mSampleView == null) {
return false;
}
switch (item.getItemId()) {
case R.id.overview:
mSampleView.showOverview();
@ -129,6 +172,14 @@ public class SkiaSampleActivity extends Activity
case R.id.save_to_pdf:
mSampleView.saveToPDF();
return true;
case R.id.glcontext_opengles:
return setOpenGLContextSettings(false, 0);
case R.id.glcontext_msaa4_opengles:
return setOpenGLContextSettings(false, 4);
case R.id.glcontext_opengl:
return setOpenGLContextSettings(true, 0);
case R.id.glcontext_msaa4_opengl:
return setOpenGLContextSettings(true, 4);
default:
return false;
}
@ -203,4 +254,16 @@ public class SkiaSampleActivity extends Activity
}
}.start();
}
private boolean setOpenGLContextSettings(boolean requestedOpenGLAPI, int requestedSampleCount) {
if (mSampleView != null &&
mSampleView.getMSAASampleCount() == requestedSampleCount &&
mSampleView.getUsesOpenGLAPI() == requestedOpenGLAPI) {
return true;
}
createSampleView(requestedOpenGLAPI, requestedSampleCount);
return true;
}
}

Просмотреть файл

@ -9,14 +9,17 @@ package com.skia;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.util.Log;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
public class SkiaSampleRenderer implements GLSurfaceView.Renderer {
private final SkiaSampleView mSampleView;
private Handler mHandler = new Handler();
private int mMSAASampleCount;
SkiaSampleRenderer(SkiaSampleView view) {
mSampleView = view;
@ -34,9 +37,24 @@ public class SkiaSampleRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
if (gl instanceof GL11) {
int value[] = new int[1];
((GL11) gl).glGetIntegerv(GL11.GL_SAMPLES, value, 0);
if (value[0] == 1) {
mMSAASampleCount = 0;
} else {
mMSAASampleCount = value[0];
}
}
gl.glClearStencil(0);
gl.glClear(GL10.GL_STENCIL_BUFFER_BIT);
init((SkiaSampleActivity)mSampleView.getContext());
init((SkiaSampleActivity)mSampleView.getContext(), mMSAASampleCount);
}
// Called by JNI and the view.
synchronized public int getMSAASampleCount() {
return mMSAASampleCount;
}
// Called by JNI
@ -71,7 +89,7 @@ public class SkiaSampleRenderer implements GLSurfaceView.Renderer {
mSampleView.requestRender();
}
native void init(SkiaSampleActivity activity);
native void init(SkiaSampleActivity activity, int msaaSampleCount);
native void term();
native void draw();
native void updateSize(int w, int h);

Просмотреть файл

@ -7,21 +7,36 @@
package com.skia;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.EGL14;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.view.MotionEvent;
public class SkiaSampleView extends GLSurfaceView {
private final SkiaSampleRenderer mSampleRenderer;
private boolean mRequestedOpenGLAPI; // true == use (desktop) OpenGL. false == use OpenGL ES.
private int mRequestedMSAASampleCount;
public SkiaSampleView(Context ctx) {
public SkiaSampleView(Context ctx, boolean useOpenGL, int msaaSampleCount) {
super(ctx);
mSampleRenderer = new SkiaSampleRenderer(this);
mRequestedMSAASampleCount = msaaSampleCount;
setEGLContextClientVersion(2);
setEGLConfigChooser(8,8,8,8,0,8);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
setEGLConfigChooser(8, 8, 8, 8, 0, 8);
} else {
mRequestedOpenGLAPI = useOpenGL;
setEGLConfigChooser(new SampleViewEGLConfigChooser());
}
setRenderer(mSampleRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
@ -162,4 +177,120 @@ public class SkiaSampleView extends GLSurfaceView {
}
});
}
public boolean getUsesOpenGLAPI() {
return mRequestedOpenGLAPI;
}
public int getMSAASampleCount() {
return mSampleRenderer.getMSAASampleCount();
}
private class SampleViewEGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
private int[] mValue;
@Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
mValue = new int[1];
int glAPIToTry;
if (mRequestedOpenGLAPI) {
glAPIToTry = EGL14.EGL_OPENGL_API;
} else {
glAPIToTry = EGL14.EGL_OPENGL_ES_API;
}
int numConfigs = 0;
int[] configSpec = null;
do {
EGL14.eglBindAPI(glAPIToTry);
int renderableType;
if (glAPIToTry == EGL14.EGL_OPENGL_API) {
renderableType = EGL14.EGL_OPENGL_ES2_BIT;
// If this API does not work, try ES next.
glAPIToTry = EGL14.EGL_OPENGL_ES_API;
} else {
renderableType = EGL14.EGL_OPENGL_BIT;
}
if (mRequestedMSAASampleCount > 0) {
configSpec = new int[] {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_STENCIL_SIZE, 8,
EGL10.EGL_RENDERABLE_TYPE, renderableType,
EGL10.EGL_SAMPLE_BUFFERS, 1,
EGL10.EGL_SAMPLES, mRequestedMSAASampleCount,
EGL10.EGL_NONE
};
if (!egl.eglChooseConfig(display, configSpec, null, 0, mValue)) {
throw new IllegalArgumentException("Could not get MSAA context count");
}
numConfigs = mValue[0];
}
if (numConfigs <= 0) {
// Try without multisampling.
configSpec = new int[] {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_STENCIL_SIZE, 8,
EGL10.EGL_RENDERABLE_TYPE, renderableType,
EGL10.EGL_NONE
};
if (!egl.eglChooseConfig(display, configSpec, null, 0, mValue)) {
throw new IllegalArgumentException("Could not get non-MSAA context count");
}
numConfigs = mValue[0];
}
} while (glAPIToTry != EGL14.EGL_OPENGL_ES_API && numConfigs == 0);
if (numConfigs <= 0) {
throw new IllegalArgumentException("No configs match configSpec");
}
// Get all matching configurations.
EGLConfig[] configs = new EGLConfig[numConfigs];
if (!egl.eglChooseConfig(display, configSpec, configs, numConfigs, mValue)) {
throw new IllegalArgumentException("Could not get config data");
}
for (int i = 0; i < configs.length; ++i) {
EGLConfig config = configs[i];
if (findConfigAttrib(egl, display, config , EGL10.EGL_RED_SIZE, 0) == 8 &&
findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0) == 8 &&
findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0) == 8 &&
findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0) == 8 &&
findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0) == 8) {
return config;
}
}
throw new IllegalArgumentException("Could not find suitable EGL config");
}
private int findConfigAttrib(EGL10 egl, EGLDisplay display,
EGLConfig config, int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0];
}
return defaultValue;
}
}
}