| /* |
| * Copyright (C) 2019 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 <memory> |
| |
| #include "android/base/Log.h" |
| #include "android/base/memory/LazyInstance.h" |
| #include "android/camera/camera-format-converters.h" |
| #include "android/virtualscene/VirtualSceneManager.h" |
| #include "emugl/common/OpenGLDispatchLoader.h" |
| |
| |
| namespace android { |
| namespace virtualscene { |
| |
| // Defines an RAII object to automatically unset the EGL context when the scope |
| // exits. Returned by RenderedCameraDevice::makeEglCurrent. |
| class ScopedEglContext { |
| DISALLOW_COPY_AND_ASSIGN(ScopedEglContext); |
| |
| public: |
| // Unset the EGL context on scope exit. |
| // |eglDispatch| - If non-null, the EGLDispatch object will be used to call |
| // eglMakeCurrent with EGL_NO_CONTEXT. If this is non-null, |
| // |eglDisplay| must also be EGL_NO_DISPLAY. |
| // |eglDisplay| - EGLDisplay handle, if |eglDispatch| is null, this must be |
| // set to EGL_NO_DISPLAY. |
| ScopedEglContext(const EGLDispatch* eglDispatch, |
| const EGLDisplay eglDisplay) |
| : mEglDispatch(eglDispatch), mEglDisplay(eglDisplay) { |
| AASSERT((eglDispatch && eglDisplay != EGL_NO_DISPLAY) || |
| (!eglDispatch && eglDisplay == EGL_NO_DISPLAY)); |
| } |
| |
| ScopedEglContext(ScopedEglContext&& other) |
| : mEglDispatch(other.mEglDispatch), mEglDisplay(other.mEglDisplay) { |
| other.mEglDispatch = nullptr; |
| other.mEglDisplay = nullptr; |
| } |
| |
| ~ScopedEglContext() { |
| if (mEglDispatch) { |
| const EGLBoolean eglResult = mEglDispatch->eglMakeCurrent( |
| mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, |
| EGL_NO_CONTEXT); |
| if (eglResult == EGL_FALSE) { |
| LOG(WARNING) << "Could not unset eglMakeCurrent error " |
| << mEglDispatch->eglGetError(); |
| } |
| } |
| } |
| |
| bool isValid() const { return mEglDispatch; } |
| |
| private: |
| const EGLDispatch* mEglDispatch; |
| EGLDisplay mEglDisplay; |
| }; |
| |
| // Abstract class for rendering scenes or frames to the emulator camera. |
| class CameraRenderer { |
| public: |
| CameraRenderer() = default; |
| virtual ~CameraRenderer() = default; |
| virtual bool initialize(const GLESv2Dispatch* gles2, |
| int width, |
| int height) = 0; |
| virtual void uninitialize() = 0; |
| virtual int64_t render() = 0; |
| }; |
| |
| |
| /******************************************************************************* |
| * RenderedCameraDevice routines |
| ******************************************************************************/ |
| |
| /* |
| * Describes a connection to an actual camera device. |
| */ |
| class RenderedCameraDevice { |
| DISALLOW_COPY_AND_ASSIGN(RenderedCameraDevice); |
| |
| public: |
| RenderedCameraDevice(std::unique_ptr<CameraRenderer> renderer); |
| ~RenderedCameraDevice(); |
| |
| CameraDevice* getCameraDevice() { return &mHeader; } |
| |
| int startCapturing(uint32_t pixelFormat, int frameWidth, int frameHeight); |
| void stopCapturing(); |
| |
| int readFrame(ClientFrame* resultFrame, |
| float rScale, |
| float gScale, |
| float bScale, |
| float expComp); |
| |
| private: |
| // Initialize EGL, returns false on failure. |
| bool initializeEgl(); |
| |
| // Set the EGL context active on the current thread. This call modifies the |
| // thread-local EGL state to make the RenderedCameraDevice's EGL context |
| // active. This may be called on any thread, but callers should be resilient |
| // to having their EGL state reset when the ScopedEglContext RAII object |
| // goes out of scope. |
| ScopedEglContext makeEglCurrent(); |
| |
| // Common camera header. |
| CameraDevice mHeader; |
| |
| std::vector<uint8_t> mFramebufferData; |
| |
| int mFramebufferWidth = 0; |
| int mFramebufferHeight = 0; |
| |
| // Dispatch tables for EGL and GLESv2 APIs. Note that these will be nullptr |
| // if there was a problem when loading the host libraries. |
| const EGLDispatch* mEglDispatch = nullptr; |
| const GLESv2Dispatch* mGles2 = nullptr; |
| |
| EGLDisplay mEglDisplay = EGL_NO_DISPLAY; |
| EGLContext mEglContext = EGL_NO_CONTEXT; |
| EGLSurface mEglSurface = EGL_NO_SURFACE; |
| bool mEglInitialized = false; |
| std::unique_ptr<CameraRenderer> renderer; |
| }; |
| |
| } // namespace virtualscene |
| } // namespace android |