diff --git a/GVRf/Framework/backend_daydream/src/main/java/org/gearvrf/DaydreamViewManager.java b/GVRf/Framework/backend_daydream/src/main/java/org/gearvrf/DaydreamViewManager.java index 6a673eb43..ac837e8ba 100644 --- a/GVRf/Framework/backend_daydream/src/main/java/org/gearvrf/DaydreamViewManager.java +++ b/GVRf/Framework/backend_daydream/src/main/java/org/gearvrf/DaydreamViewManager.java @@ -146,7 +146,6 @@ void onDrawEye(int eye) { mRenderBundle.getPostEffectRenderTextureB()); captureRightEye(renderTarget,false); } - captureFinish(); } void setCameraRig(GVRCameraRig cameraRig) { diff --git a/GVRf/Framework/backend_oculus/src/main/java/org/gearvrf/OvrViewManager.java b/GVRf/Framework/backend_oculus/src/main/java/org/gearvrf/OvrViewManager.java index 6c5268fcd..bf13414a3 100644 --- a/GVRf/Framework/backend_oculus/src/main/java/org/gearvrf/OvrViewManager.java +++ b/GVRf/Framework/backend_oculus/src/main/java/org/gearvrf/OvrViewManager.java @@ -196,8 +196,6 @@ void onDrawEye(int eye, int swapChainIndex, boolean use_multiview) { captureRightEye(renderTarget, true); captureLeftEye(renderTarget, true); - captureFinish(); - if (DEBUG_STATS) { mTracerDrawEyes1.leave(); mTracerDrawEyes2.leave(); @@ -217,7 +215,6 @@ void onDrawEye(int eye, int swapChainIndex, boolean use_multiview) { mRenderBundle.getPostEffectRenderTextureB()); captureRightEye(renderTarget, false); - captureFinish(); if (DEBUG_STATS) { mTracerDrawEyes1.leave(); mTracerDrawEyes.leave(); @@ -236,6 +233,7 @@ void onDrawEye(int eye, int swapChainIndex, boolean use_multiview) { renderTarget.cullFromCamera(mMainScene, mainCameraRig.getCenterCamera(), mRenderBundle.getShaderManager()); captureCenterEye(renderTarget, false); + captureSticker(); renderTarget.render(mMainScene, leftCamera, mRenderBundle.getShaderManager(), mRenderBundle.getPostEffectRenderTextureA(), mRenderBundle.getPostEffectRenderTextureB()); captureLeftEye(renderTarget, false); diff --git a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContext.java b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContext.java index 2f6bf56eb..70d763cf2 100644 --- a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContext.java +++ b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContext.java @@ -584,6 +584,8 @@ protected synchronized static void resetOnRestart() { */ public abstract void captureScreenCenter(GVRScreenshotCallback callback); + abstract boolean captureSticker(GVRScreenshotCallback callback, int pboIndex); + /** * Capture a 2D screenshot from the position of left eye. * diff --git a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContextProxy.java b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContextProxy.java index ca4bd4d24..33538de47 100644 --- a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContextProxy.java +++ b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRContextProxy.java @@ -127,6 +127,10 @@ public void captureScreenCenter(GVRScreenshotCallback callback) { mContext.get().captureScreenCenter(callback); } + public boolean captureSticker(GVRScreenshotCallback callback, int pboIndex) { + return mContext.get().captureSticker(callback, pboIndex); + } + public void captureScreenLeft(GVRScreenshotCallback callback) { mContext.get().captureScreenLeft(callback); } diff --git a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRRenderBundle.java b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRRenderBundle.java index f42afd43c..3727c7e66 100644 --- a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRRenderBundle.java +++ b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRRenderBundle.java @@ -24,6 +24,8 @@ class GVRRenderBundle { private GVRRenderTexture mPostEffectRenderTextureA = null; private GVRRenderTexture mPostEffectRenderTextureB = null; private GVRRenderTarget mEyeCaptureRenderTarget = null; + // Three render targets for sticker generation + private GVRRenderTarget mStickerRenderTarget[] = {null, null, null}; protected int mSampleCount; protected int mWidth, mHeight; @@ -92,6 +94,15 @@ public GVRRenderTarget getEyeCaptureRenderTarget() { } return mEyeCaptureRenderTarget; } + + public GVRRenderTarget getStickerRenderTarget(int index) { + if(mStickerRenderTarget[index] == null){ + mStickerRenderTarget[index] = new GVRRenderTarget(new GVRRenderTexture(mGVRContext, mWidth, mHeight, mSampleCount), mGVRContext.getMainScene()); + mStickerRenderTarget[index].setCamera(mGVRContext.getMainScene().getMainCameraRig().getCenterCamera()); + } + return mStickerRenderTarget[index]; + } + void beginRendering(int bufferIdx, GVRViewManager.EYE eye) { getRenderTexture(bufferIdx,eye).beginRendering(); } diff --git a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRSticker.java b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRSticker.java new file mode 100644 index 000000000..3bb5b1d90 --- /dev/null +++ b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRSticker.java @@ -0,0 +1,150 @@ +/* Copyright 2015 Samsung Electronics Co., LTD + * + * 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 org.gearvrf; + +import android.graphics.Bitmap; +import android.os.Environment; +import android.util.Log; + +import org.gearvrf.utility.Threads; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * This class takes screenshots at a specified interval and writes the output PNG files to GearVRFScreenshots directory. + * The capturing can be stopped by calling {@link GVRSticker#stop()} + * The images can be used to create Stickers (a GIF animation) + */ + +public class GVRSticker { + private final GVRContext mGVRContext; + private final String mTag; + private final String mDirectory; + private final long mInterval; + private boolean mCaptureFlag = true; + private final static String TAG = "GVRSticker"; + + /** + * Constructor takes the following parameters + * @param gvrContext + * @param tag + * Name for outputting PNG's to the SD Card along with appended frame ID + * @param interval + * Time in milliseconds to take screenshot at that interval + */ + public GVRSticker(GVRContext gvrContext, String tag, long interval){ + mGVRContext = gvrContext; + mTag = tag; + mInterval = interval; + + File sdcard = Environment.getExternalStorageDirectory(); + mDirectory = sdcard.getAbsolutePath() + "/GearVRFScreenshots/"; + File d = new File(mDirectory); + d.mkdirs(); + } + + private boolean lastScreenshotFinished[] = {true, true, true}; + private int pboIndex = 0; + + /** + * Initiate's the screenshot capturing + * Captures images every {@link GVRSticker#mInterval} milliseconds + */ + public void captureScreen() + { + mCaptureFlag = true; + Threads.spawn(new Runnable() + { + public void run() + { + int frame = 0; + boolean lastStickerCall; + while(mCaptureFlag) { + if (lastScreenshotFinished[pboIndex]) { + lastStickerCall = mGVRContext + .captureSticker(newScreenshotCallback(frame, pboIndex), pboIndex); + if(lastStickerCall) { + lastScreenshotFinished[pboIndex] = false; + pboIndex = (pboIndex + 1) % 3; + frame++; + } + } + else{ + Log.e(TAG, "Sticker skipped since previous read is not completed"); + } + try { + Thread.sleep(mInterval); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }); + } + + /** + * Stop's the screenshot thread + */ + public void stop(){ + mCaptureFlag = false; + } + + private GVRScreenshotCallback newScreenshotCallback(final int frame, final int currentPboIndex) + { + return new GVRScreenshotCallback() + { + @Override + public void onScreenCaptured(Bitmap bitmap) + { + if (bitmap != null) + { + File file = new File(mDirectory + mTag +"_"+ frame +"_" + ".png"); + FileOutputStream outputStream = null; + try + { + outputStream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + finally + { + try + { + outputStream.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + else + { + Log.e(TAG, "Returned Bitmap is null for frame " + frame); + } + + // enable next screenshot + lastScreenshotFinished[currentPboIndex] = true; + } + }; + } +} diff --git a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRViewManager.java b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRViewManager.java index caacb98d7..d348b8c2b 100644 --- a/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRViewManager.java +++ b/GVRf/Framework/framework/src/main/java/org/gearvrf/GVRViewManager.java @@ -559,6 +559,8 @@ public GVRShaderManager getShaderManager() { protected GVRScreenshotCallback mScreenshotLeftCallback; protected GVRScreenshotCallback mScreenshotRightCallback; protected GVRScreenshot3DCallback mScreenshot3DCallback; + protected GVRScreenshotCallback mStickerCallback; + protected int mPboIndex = 0; @Override public void captureScreenCenter(GVRScreenshotCallback callback) { @@ -569,6 +571,21 @@ public void captureScreenCenter(GVRScreenshotCallback callback) { } } + @Override + public boolean captureSticker(GVRScreenshotCallback callback, int pboIndex) { + // Avoids making null of previous mStickerCallback if it is not completed + if(mStickerCallback != null) + return false; + if (callback == null) { + throw new IllegalArgumentException("callback should not be null."); + } else { + mStickerCallback = callback; + mPboIndex = pboIndex; + } + + return true; + } + @Override public void captureScreenLeft(GVRScreenshotCallback callback) { if (callback == null) { @@ -593,21 +610,41 @@ public void captureScreen3D(GVRScreenshot3DCallback callback) { } protected void readRenderResult(GVRRenderTarget renderTarget, GVRViewManager.EYE eye, boolean useMultiview) { - if (mReadbackBuffer == null) { + if (mReadbackBuffer[mPboIndex] == null) { + final VrAppSettings settings = mApplication.getAppSettings(); + final VrAppSettings.EyeBufferParams eyeBufferParams = settings.getEyeBufferParams(); + mReadbackBufferWidth = eyeBufferParams.getResolutionWidth(); + mReadbackBufferHeight = eyeBufferParams.getResolutionHeight(); + + mReadbackBuffer[mPboIndex] = ByteBuffer.allocateDirect(mReadbackBufferWidth * mReadbackBufferHeight * 4); + mReadbackBuffer[mPboIndex].order(ByteOrder.nativeOrder()); + } + readRenderResultNative(mReadbackBuffer[mPboIndex],renderTarget.getNative(), eye.ordinal(), useMultiview ); + } + + protected void readRenderResultInPBO(int pboIndex) { + if (mReadbackBuffer[mPboIndex] == null) { final VrAppSettings settings = mApplication.getAppSettings(); final VrAppSettings.EyeBufferParams eyeBufferParams = settings.getEyeBufferParams(); mReadbackBufferWidth = eyeBufferParams.getResolutionWidth(); mReadbackBufferHeight = eyeBufferParams.getResolutionHeight(); - mReadbackBuffer = ByteBuffer.allocateDirect(mReadbackBufferWidth * mReadbackBufferHeight * 4); - mReadbackBuffer.order(ByteOrder.nativeOrder()); + mReadbackBuffer[pboIndex] = ByteBuffer.allocateDirect(mReadbackBufferWidth * mReadbackBufferHeight * 4); + mReadbackBuffer[pboIndex].order(ByteOrder.nativeOrder()); } - readRenderResultNative(mReadbackBuffer,renderTarget.getNative(), eye.ordinal(), useMultiview ); + + readRenderResultInPBONative(pboIndex); + } + + protected void readRenderResultFromPBO(ByteBuffer readbackBuffer, int pboIndex) { + if(readbackBuffer == null) + return; + readRenderResultFromPBONative(readbackBuffer, pboIndex); } protected void returnScreenshotToCaller(final GVRScreenshotCallback callback, final int width, final int height) { // run the callback function in a background thread - final byte[] byteArray = Arrays.copyOf(mReadbackBuffer.array(), mReadbackBuffer.array().length); + final byte[] byteArray = Arrays.copyOf(mReadbackBuffer[mPboIndex].array(), mReadbackBuffer[mPboIndex].array().length); Threads.spawn(new Runnable() { public void run() { final Bitmap capturedBitmap = ImageUtils.generateBitmapFlipV(byteArray, width, height); @@ -690,6 +727,7 @@ private void captureEye(GVRScreenshotCallback callback, GVRRenderTarget renderTa } readRenderResult(renderTarget,eye,useMultiview); returnScreenshotToCaller(callback, mReadbackBufferWidth, mReadbackBufferHeight); + mReadbackBuffer[mPboIndex] = null; } // capture center eye @@ -727,8 +765,8 @@ protected void captureCenterEye(GVRRenderTarget renderTarget, boolean isMultivie renderTarget.endRendering(); final Bitmap bitmap = Bitmap.createBitmap(mReadbackBufferWidth, mReadbackBufferHeight, Bitmap.Config.ARGB_8888); - mReadbackBuffer.rewind(); - bitmap.copyPixelsFromBuffer(mReadbackBuffer); + mReadbackBuffer[mPboIndex].rewind(); + bitmap.copyPixelsFromBuffer(mReadbackBuffer[mPboIndex]); final GVRScreenshotCallback callback = mScreenshotCenterCallback; Threads.spawn(new Runnable() { public void run() { @@ -739,6 +777,55 @@ public void run() { mScreenshotCenterCallback = null; } + // Capture sticker + protected void captureSticker() { + if (mStickerCallback == null) { + return; + } + + // TODO: when we will use multithreading, create new camera using centercamera as we are adding posteffects into it + final GVRCamera centerCamera = mMainScene.getMainCameraRig().getCenterCamera(); + final GVRMaterial postEffect = new GVRMaterial(this, GVRMaterial.GVRShaderType.HorizontalFlip.ID); + centerCamera.addPostEffect(postEffect); + + GVRRenderTexture posteffectRenderTextureA = mRenderBundle.getPostEffectRenderTextureA(); + GVRRenderTexture posteffectRenderTextureB = mRenderBundle.getPostEffectRenderTextureB(); + + GVRRenderTarget renderTarget = mRenderBundle.getStickerRenderTarget(mPboIndex); + renderTarget.cullFromCamera(mMainScene, centerCamera ,mRenderBundle.getShaderManager()); + + renderTarget.beginRendering(centerCamera); + renderTarget.render(mMainScene,centerCamera, mRenderBundle.getShaderManager(), posteffectRenderTextureA, posteffectRenderTextureB); + centerCamera.removePostEffect(postEffect); + readRenderResultInPBO(mPboIndex); + renderTarget.endRendering(); + + // Read the previous PBO's result into readbackBuffer + int pboIndex = (mPboIndex - 1) < 0 ? 2 : mPboIndex - 1; + final ByteBuffer readbackBuffer = mReadbackBuffer[pboIndex]; + + if(readbackBuffer != null) { + readRenderResultFromPBO(readbackBuffer, pboIndex); + readbackBuffer.rewind(); + } + + final GVRScreenshotCallback callback = mStickerCallback; + + Threads.spawn(new Runnable() { + public void run() { + Bitmap bitmap = null; + // Copying asynchronously readback buffers data into bitmap + if(readbackBuffer != null) { + bitmap = Bitmap.createBitmap(mReadbackBufferWidth, mReadbackBufferHeight, Bitmap.Config.ARGB_8888); + bitmap.copyPixelsFromBuffer(readbackBuffer); + } + callback.onScreenCaptured(bitmap); + } + }); + + mStickerCallback = null; + } + private void renderOneCameraAndAddToList(final GVRPerspectiveCamera centerCamera, final Bitmap[] bitmaps, int index, GVRRenderTarget renderTarget, GVRRenderTexture postEffectRenderTextureA, GVRRenderTexture postEffectRenderTextureB ) { @@ -747,8 +834,8 @@ private void renderOneCameraAndAddToList(final GVRPerspectiveCamera centerCamera readRenderResult(renderTarget,EYE.CENTER, false); bitmaps[index] = Bitmap.createBitmap(mReadbackBufferWidth, mReadbackBufferHeight, Bitmap.Config.ARGB_8888); - mReadbackBuffer.rewind(); - bitmaps[index].copyPixelsFromBuffer(mReadbackBuffer); + mReadbackBuffer[mPboIndex].rewind(); + bitmaps[index].copyPixelsFromBuffer(mReadbackBuffer[mPboIndex]); } private void renderSixCamerasAndReadback(final GVRCameraRig mainCameraRig, final Bitmap[] bitmaps, GVRRenderTarget renderTarget, boolean isMultiview) { @@ -804,12 +891,6 @@ private void renderSixCamerasAndReadback(final GVRCameraRig mainCameraRig, final renderTarget.endRendering(); } - protected void captureFinish() { - if (mScreenshotLeftCallback == null && mScreenshotRightCallback == null - && mScreenshotCenterCallback == null && mScreenshot3DCallback == null) { - mReadbackBuffer = null; - } - } GVRGearCursorController.ControllerReader mControllerReader; private final GVRScriptManager mScriptManager; protected final GVRApplication mApplication; @@ -834,15 +915,16 @@ protected void captureFinish() { protected GVRMain mMain; - protected ByteBuffer mReadbackBuffer; + protected ByteBuffer mReadbackBuffer[] = {null, null, null}; protected int mReadbackBufferWidth; protected int mReadbackBufferHeight; protected native void makeShadowMaps(long scene, GVRScene javaSceneObject, long shader_manager, int width, int height); protected native void cullAndRender(long render_target, long scene, GVRScene javaSceneObject, long shader_manager, long postEffectRenderTextureA, long postEffectRenderTextureB); private native static void readRenderResultNative(Object readbackBuffer, long renderTarget, int eye, boolean useMultiview); + private native static void readRenderResultInPBONative(int pboIndex); + private native static void readRenderResultFromPBONative(Object readbackBuffer, int pboIndex); private static final String TAG = "GVRViewManager"; - } diff --git a/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.cpp b/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.cpp index c2dacf099..81bba6c6d 100644 --- a/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.cpp +++ b/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.cpp @@ -713,5 +713,46 @@ namespace gvr copy_mesh->setTriangles(faces, faces_size); } + bool GLRenderer::readRenderResultInPBO(int pboIndex) { + static GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT,viewport); + + GLuint* &pbos = gRenderer->getPBOs(); + if(pbos == NULL){ + pbos = new GLuint[3]; + glGenBuffers(3, pbos); + + long neededCapacity = viewport[2] * viewport[3] * 4; + for(int i = 0; i < 3; i++){ + glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[i]); + glBufferData(GL_PIXEL_PACK_BUFFER, neededCapacity, NULL, GL_DYNAMIC_READ); + } + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + } + + glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[pboIndex]); + glReadPixels(0, 0, viewport[2], viewport[3], GL_RGBA, GL_UNSIGNED_BYTE, 0); + return true; + } + + bool GLRenderer::readRenderResultFromPBO(uint8_t *readback_buffer, int pboIndex) { + static GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT,viewport); + long pboSize = viewport[2] * viewport[3] * 4; + + GLuint * pbos = gRenderer->getPBOs(); + glBindBuffer(GL_PIXEL_PACK_BUFFER, pbos[pboIndex]); + + uint8_t* ptr = (uint8_t*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, pboSize, GL_MAP_READ_BIT); + + if (NULL != ptr) { + memcpy(readback_buffer, ptr, pboSize); + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + } + else { + LOGE("Failed to map the buffer"); + } + return true; + } } diff --git a/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.h b/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.h index ea50e99a2..cc21a7dde 100644 --- a/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.h +++ b/GVRf/Framework/framework/src/main/jni/engine/renderer/gl_renderer.h @@ -65,6 +65,11 @@ class GLRenderer: public Renderer { if(transform_ubo_[1]) delete transform_ubo_[1]; + GLuint* &pbos = getPBOs(); + if(pbos != NULL) { + glDeleteBuffers(3, pbos); + } + } public: @@ -103,6 +108,8 @@ class GLRenderer: public Renderer { GLUniformBlock* getTransformUbo(int index) { return transform_ubo_[index]; } virtual void updatePostEffectMesh(Mesh*); virtual bool renderWithShader(RenderState& rstate, Shader* shader, RenderData* renderData, ShaderData* shaderData, int); + virtual bool readRenderResultInPBO(int); + virtual bool readRenderResultFromPBO(uint8_t *readback_buffer, int pboIndex); private: virtual void renderMesh(RenderState& rstate, RenderData* render_data); diff --git a/GVRf/Framework/framework/src/main/jni/engine/renderer/renderer.h b/GVRf/Framework/framework/src/main/jni/engine/renderer/renderer.h index b445e0ac6..975d0ed55 100644 --- a/GVRf/Framework/framework/src/main/jni/engine/renderer/renderer.h +++ b/GVRf/Framework/framework/src/main/jni/engine/renderer/renderer.h @@ -202,10 +202,13 @@ class Renderer { } return nullptr; } + virtual bool readRenderResultInPBO(int) = 0; + virtual bool readRenderResultFromPBO(uint8_t *, int) = 0; private: RenderTarget* mLeftRenderTarget[3]; RenderTarget* mRightRenderTarget[3]; RenderTarget* mMultiviewRenderTarget[3]; + GLuint * pbos = NULL; static bool isVulkan_; virtual void build_frustum(float frustum[6][4], const float *vp_matrix); virtual void frustum_cull(glm::vec3 camera_position, SceneObject *object, @@ -244,6 +247,9 @@ class Renderer { bool useStencilBuffer(){ return useStencilBuffer_; } + GLuint* & getPBOs(){ + return pbos; + } }; extern Renderer* gRenderer; } diff --git a/GVRf/Framework/framework/src/main/jni/engine/renderer/vulkan_renderer.h b/GVRf/Framework/framework/src/main/jni/engine/renderer/vulkan_renderer.h index 001f78b12..8fae5d37f 100644 --- a/GVRf/Framework/framework/src/main/jni/engine/renderer/vulkan_renderer.h +++ b/GVRf/Framework/framework/src/main/jni/engine/renderer/vulkan_renderer.h @@ -135,7 +135,8 @@ class VulkanRenderer: public Renderer { virtual bool renderWithShader(RenderState& rstate, Shader* shader, RenderData* renderData, ShaderData* shaderData, int); virtual void updatePostEffectMesh(Mesh*); - + virtual bool readRenderResultInPBO(int){} + virtual bool readRenderResultFromPBO(uint8_t *readback_buffer, int pboIndex){} private: VulkanCore* vulkanCore_; void renderMesh(RenderState& rstate, RenderData* render_data){} diff --git a/GVRf/Framework/framework/src/main/jni/view_manager_jni.cpp b/GVRf/Framework/framework/src/main/jni/view_manager_jni.cpp index fc536f3e2..cae0b1764 100644 --- a/GVRf/Framework/framework/src/main/jni/view_manager_jni.cpp +++ b/GVRf/Framework/framework/src/main/jni/view_manager_jni.cpp @@ -85,6 +85,13 @@ extern "C" { Java_org_gearvrf_GVRViewManager_readRenderResultNative(JNIEnv *env, jclass clazz, jobject jreadback_buffer, jlong jrenderTarget, jint eye, jboolean useMultiview); + JNIEXPORT void JNICALL + Java_org_gearvrf_GVRViewManager_readRenderResultInPBONative(JNIEnv *env, jclass clazz, + jint pboIndex); + + JNIEXPORT void JNICALL + Java_org_gearvrf_GVRViewManager_readRenderResultFromPBONative(JNIEnv *env, jclass clazz, + jobject jreadback_buffer, jint pboIndex); } // extern "C" @@ -98,4 +105,15 @@ JNIEXPORT void JNICALL Java_org_gearvrf_GVRViewManager_readRenderResultNative(JN } renderTexture->readRenderResult(readback_buffer); } + + JNIEXPORT void JNICALL Java_org_gearvrf_GVRViewManager_readRenderResultInPBONative(JNIEnv *env, jclass clazz, + jint pboIndex){ + gRenderer->readRenderResultInPBO(pboIndex); + } + + JNIEXPORT void JNICALL Java_org_gearvrf_GVRViewManager_readRenderResultFromPBONative(JNIEnv *env, jclass clazz, + jobject jreadback_buffer, jint pboIndex){ + uint8_t *readback_buffer = (uint8_t*) env->GetDirectBufferAddress(jreadback_buffer); + gRenderer->readRenderResultFromPBO(readback_buffer, pboIndex); + } } \ No newline at end of file diff --git a/GVRf/Framework/framework/src/main/res/raw/vertex_template_multitex.vsh b/GVRf/Framework/framework/src/main/res/raw/vertex_template_multitex.vsh index 23613a5ca..ab59022fd 100644 --- a/GVRf/Framework/framework/src/main/res/raw/vertex_template_multitex.vsh +++ b/GVRf/Framework/framework/src/main/res/raw/vertex_template_multitex.vsh @@ -143,19 +143,12 @@ void main() { viewspace_normal = vertex.viewspace_normal; view_direction = vertex.view_direction; #ifdef HAS_MULTIVIEW -<<<<<<< HEAD bool render_mask = (u_render_mask & (gl_ViewID_OVR + uint(1))) > uint(0) ? true : false; mat4 mvp = u_mvp_[gl_ViewID_OVR]; if(!render_mask) mvp = mat4(0.0); // if render_mask is not set for particular eye, dont render that object gl_Position = mvp * vertex.local_position; -======= - bool render_mask = (u_render_mask & (gl_ViewID_OVR + uint(1))) > uint(0) ? true : false; - mat4 mvp = u_mvp_[gl_ViewID_OVR]; - if(!render_mask) - mvp = mat4(0.0); // if render_mask is not set for particular eye, dont render that object - gl_Position = mvp * vertex.local_position; ->>>>>>> normalmap + #else gl_Position = u_mvp * vertex.local_position; #endif