diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-12-10 20:37:41 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-12-10 20:37:41 +0000 |
commit | a3b84d41efbbc5ab1e050a33d66dca4d1c44c9e3 (patch) | |
tree | 5dfdcb17f8335f373d0071c201c511bb649ae37b | |
parent | bc55eec80ef376208b3c1bfc65d8dc8b672d59f0 (diff) |
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
8 files changed, 293 insertions, 23 deletions
diff --git a/include/views/SkOSWindow_Android.h b/include/views/SkOSWindow_Android.h index 77c156cd23..ae4e880039 100644 --- a/include/views/SkOSWindow_Android.h +++ b/include/views/SkOSWindow_Android.h @@ -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() {} diff --git a/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp b/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp index 6098643b99..7ce43cc158 100644 --- a/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp +++ b/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.cpp @@ -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(); diff --git a/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.h b/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.h index 5d371235fe..023f679425 100644 --- a/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.h +++ b/platform_tools/android/app/jni/com_skia_SkiaSampleRenderer.h @@ -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 diff --git a/platform_tools/android/app/res/menu/action_bar.xml b/platform_tools/android/app/res/menu/action_bar.xml index 2e8cf70125..72e135e43b 100644 --- a/platform_tools/android/app/res/menu/action_bar.xml +++ b/platform_tools/android/app/res/menu/action_bar.xml @@ -43,6 +43,32 @@ 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" /> diff --git a/platform_tools/android/app/res/values/strings.xml b/platform_tools/android/app/res/values/strings.xml index 610ef380b2..b0b4e7b74b 100644 --- a/platform_tools/android/app/res/values/strings.xml +++ b/platform_tools/android/app/res/values/strings.xml @@ -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>
\ No newline at end of file diff --git a/platform_tools/android/app/src/com/skia/SkiaSampleActivity.java b/platform_tools/android/app/src/com/skia/SkiaSampleActivity.java index 0a7a569728..090d6ad14c 100644 --- a/platform_tools/android/app/src/com/skia/SkiaSampleActivity.java +++ b/platform_tools/android/app/src/com/skia/SkiaSampleActivity.java @@ -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(); } @@ -100,7 +112,38 @@ public class SkiaSampleActivity extends Activity } @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; + } } diff --git a/platform_tools/android/app/src/com/skia/SkiaSampleRenderer.java b/platform_tools/android/app/src/com/skia/SkiaSampleRenderer.java index 1479c92396..d8fb8845b4 100644 --- a/platform_tools/android/app/src/com/skia/SkiaSampleRenderer.java +++ b/platform_tools/android/app/src/com/skia/SkiaSampleRenderer.java @@ -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); diff --git a/platform_tools/android/app/src/com/skia/SkiaSampleView.java b/platform_tools/android/app/src/com/skia/SkiaSampleView.java index 0d493c96df..b1f7318319 100644 --- a/platform_tools/android/app/src/com/skia/SkiaSampleView.java +++ b/platform_tools/android/app/src/com/skia/SkiaSampleView.java @@ -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; + } + + } } |