1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #pragma once
18 
19 #include <EGL/egl.h>
20 #include <GLES/gl.h>
21 
22 #include <memory>
23 #include <unordered_map>
24 #include <unordered_set>
25 
26 #include "ColorBuffer.h"
27 #include "Handle.h"
28 #include "gl/ColorBufferGl.h"
29 #include "gl/EmulatedEglContext.h"
30 
31 namespace gfxstream {
32 namespace gl {
33 
34 // A class used to model a guest-side window surface. The implementation
35 // uses a host Pbuffer to act as the EGL rendering surface instead.
36 class EmulatedEglWindowSurface {
37   public:
38     // Create a new EmulatedEglWindowSurface instance.
39     // |display| is the host EGLDisplay value.
40     // |config| is the host EGLConfig value.
41     // |width| and |height| are the initial size of the Pbuffer.
42     // Return a new EmulatedEglWindowSurface instance on success, or NULL on
43     // failure.
44     static std::unique_ptr<EmulatedEglWindowSurface> create(EGLDisplay display,
45                                                             EGLConfig config,
46                                                             int width,
47                                                             int height,
48                                                             HandleType hndl);
49 
50     // Destructor.
51     ~EmulatedEglWindowSurface();
52 
53     // Retrieve the host EGLSurface of the EmulatedEglWindowSurface's Pbuffer.
getEGLSurface()54     EGLSurface getEGLSurface() const { return mSurface; }
55 
56     // Attach a ColorBuffer to this EmulatedEglWindowSurface.
57     // Once attached, calling flushColorBuffer() will copy the Pbuffer's
58     // pixels to the color buffer.
59     //
60     // IMPORTANT: This automatically resizes the Pbuffer's to the ColorBuffer's
61     // dimensions. Potentially losing pixel values in the process.
62     void setColorBuffer(ColorBufferPtr p_colorBuffer);
63 
64     // Retrieves a pointer to the attached color buffer.
getAttachedColorBuffer()65     ColorBuffer* getAttachedColorBuffer() const {
66         return mAttachedColorBuffer.get();
67     }
68 
69     // Copy the Pbuffer's pixels to the attached color buffer.
70     // Returns true on success, or false on error (e.g. if there is no
71     // attached color buffer).
72     bool flushColorBuffer();
73 
74     // Used by bind() below.
75     enum BindType {
76         BIND_READ,
77         BIND_DRAW,
78         BIND_READDRAW
79     };
80 
81     // TODO(digit): What is this used for exactly? For example, the
82     // mReadContext is never used by this class. The mDrawContext is only
83     // used temporarily during flushColorBuffer() operation, and could be
84     // passed as a parameter to the function instead. Maybe this is only used
85     // to increment reference counts on the smart pointers.
86     //
87     // Bind a context to the EmulatedEglWindowSurface (huh? Normally you would bind a
88     // surface to the context, not the other way around)
89     //
90     // |p_ctx| is a EmulatedEglContext pointer.
91     // |p_bindType| is the type of bind. For BIND_READ, this assigns |p_ctx|
92     // to mReadContext, for BIND_DRAW, it assigns it to mDrawContext, and for
93     // for BIND_READDRAW, it assigns it to both.
94     void bind(EmulatedEglContextPtr p_ctx, BindType p_bindType);
95 
96     GLuint getWidth() const;
97     GLuint getHeight() const;
98 
99     void onSave(android::base::Stream* stream) const;
100     static std::unique_ptr<EmulatedEglWindowSurface> onLoad(
101       android::base::Stream* stream,
102       EGLDisplay display,
103       const ColorBufferMap& colorBuffers,
104       const EmulatedEglContextMap& contexts);
105 
106     HandleType getHndl() const;
107 
108   private:
109     EmulatedEglWindowSurface(const EmulatedEglWindowSurface& other) = delete;
110 
111     EmulatedEglWindowSurface(EGLDisplay display, EGLConfig config, HandleType hndl);
112 
113     bool resize(unsigned int p_width, unsigned int p_height);
114 
115     EGLSurface mSurface = EGL_NO_SURFACE;
116     ColorBufferPtr mAttachedColorBuffer;
117     EmulatedEglContextPtr mReadContext;
118     EmulatedEglContextPtr mDrawContext;
119     GLuint mWidth = 0;
120     GLuint mHeight = 0;
121     EGLConfig mConfig = nullptr;
122     EGLDisplay mDisplay = EGL_NO_DISPLAY;
123     HandleType mHndl;
124 };
125 
126 typedef std::shared_ptr<EmulatedEglWindowSurface> EmulatedEglWindowSurfacePtr;
127 typedef std::unordered_map<HandleType, std::pair<EmulatedEglWindowSurfacePtr, HandleType>> EmulatedEglWindowSurfaceMap;
128 typedef std::unordered_set<HandleType> EmulatedEglWindowSurfaceSet;
129 
130 }  // namespace gl
131 }  // namespace gfxstream
132