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 #include <stdio.h>
18 #include <stdlib.h>
19 #include <assert.h>
20 #include "RenderingThread.h"
21 #include "Renderer.h"
22
23 // include operating-system dependent windowing system impelemntation
24 #ifdef _WIN32
25 # error "WINDOWS IS NOT SUPPORTED AT THE MOMENT"
26 #elif defined __APPLE__
27 # error "Apple OS-X IS NOT SUPPORTED"
28 #elif defined (__unix__)
29 # include "X11Windowing.h"
30 #endif
31
32
33
34
35
36 Renderer * Renderer::m_instance = NULL;
37
instance()38 Renderer * Renderer::instance()
39 {
40 if (m_instance == NULL) m_instance = new Renderer;
41 return m_instance;
42 }
43
Renderer()44 Renderer::Renderer()
45 {
46 // Unix specific, use your platform specific windowing implementation
47 #ifdef __unix__
48 m_nw = new X11Windowing;
49 #endif
50
51 m_dpy = eglGetDisplay(m_nw->getNativeDisplay());
52 EGLint major, minor;
53 eglInitialize(m_dpy, &major, &minor);
54 fprintf(stderr, "egl initialized : %d.%d\n", major, minor);
55 }
56
createSurface(RenderingThread * thread,const ClientHandle & handle)57 int Renderer::createSurface(RenderingThread *thread, const ClientHandle & handle)
58 {
59 android::Mutex::Autolock(this->m_mutex);
60
61 assert(m_surfaces.find(handle) == m_surfaces.end());
62 if (handle.handle == 0) {
63 fprintf(stderr, "trying to create surface for EGL_NO_SURFACE !!!\n");
64 return -1;
65 } else {
66 RendererSurface *surface = RendererSurface::create(m_dpy, RendererSurface::CONFIG_DEPTH, m_nw);
67 if (surface == NULL) {
68 printf("failed to create surface !!\n");
69 return -1;
70 }
71 m_surfaces.insert(SurfaceMap::value_type(handle, surface));
72 }
73 return 0;
74 }
75
destroySurface(RenderingThread * thread,const ClientHandle & handle)76 int Renderer::destroySurface(RenderingThread *thread, const ClientHandle &handle)
77 {
78 android::Mutex::Autolock(this->m_mutex);
79
80 SurfaceMap::iterator i = m_surfaces.find(handle);
81 if (i == m_surfaces.end()) {
82 printf("removing surface that doesn't exists\n");
83 return -1;
84 }
85 if (i->second->destroy(m_nw)) {
86 m_surfaces.erase(handle);
87 }
88 return 0;
89 }
90
createContext(RenderingThread * thread,const ClientHandle & handle,ClientHandle shareCtx,int version)91 int Renderer::createContext(RenderingThread *thread, const ClientHandle &handle, ClientHandle shareCtx, int version)
92 {
93 android::Mutex::Autolock(this->m_mutex);
94
95 assert(m_ctxs.find(handle) == m_ctxs.end());
96 RendererContext *shared = NULL;
97 if (shareCtx.handle != 0) {
98 ContextMap::iterator sctx = m_ctxs.find(shareCtx);
99 if (sctx != m_ctxs.end()) {
100 shared = sctx->second;
101 }
102 }
103
104 RendererContext *ctx =
105 RendererContext::create(m_dpy,
106 RendererSurface::getEglConfig(m_dpy, RendererSurface::CONFIG_DEPTH),
107 shared, version);
108 if (ctx == NULL) {
109 fprintf(stderr, "failed to create context\n");
110 return -1;
111 }
112 m_ctxs.insert(ContextMap::value_type(handle, ctx));
113 return 0;
114 }
115
destroyContext(RenderingThread * thread,const ClientHandle & handle)116 int Renderer::destroyContext(RenderingThread *thread, const ClientHandle &handle)
117 {
118 android::Mutex::Autolock(this->m_mutex);
119
120 ContextMap::iterator i = m_ctxs.find(handle);
121 if (i == m_ctxs.end()) {
122 printf("removing context that doesn't exists\n");
123 return -1;
124 }
125 if (i->second->destroy()) {
126 m_ctxs.erase(handle);
127 }
128 return 0;
129 }
130
makeCurrent(RenderingThread * thread,const ClientHandle & drawSurface,const ClientHandle & readSurface,const ClientHandle & ctx)131 int Renderer::makeCurrent(RenderingThread *thread,
132 const ClientHandle &drawSurface,
133 const ClientHandle &readSurface,
134 const ClientHandle & ctx)
135 {
136 android::Mutex::Autolock(this->m_mutex);
137
138 RendererContext *currentContext = thread->currentContext();
139
140 ContextMap::iterator c = m_ctxs.find(ctx);
141 EGLContext eglContext;
142 if (ctx.handle != 0 && c != m_ctxs.end()) {
143 if (c->second != currentContext) {
144 // new context is set
145 if (currentContext != NULL) currentContext->unref();
146 c->second->ref();
147 eglContext = c->second->eglContext();
148 thread->setCurrentContext(c->second);
149 thread->glDecoder().setContextData(&c->second->decoderContextData());
150 thread->gl2Decoder().setContextData(&c->second->decoderContextData());
151 } else {
152 // same context is already set
153 eglContext = c->second->eglContext();
154 }
155 } else {
156 eglContext = EGL_NO_CONTEXT;
157 if (currentContext != NULL) currentContext->unref();
158 thread->setCurrentContext(NULL);
159 thread->glDecoder().setContextData(NULL);
160 thread->gl2Decoder().setContextData(NULL);
161 }
162
163 EGLSurface draw = EGL_NO_SURFACE;
164 EGLSurface read = EGL_NO_SURFACE;
165 SurfaceMap::iterator i;
166 i = m_surfaces.find(drawSurface); if (i != m_surfaces.end()) draw = i->second->eglSurface();
167 i = m_surfaces.find(readSurface); if (i != m_surfaces.end()) read = i->second->eglSurface();
168
169 return eglMakeCurrent(m_dpy, draw, read, eglContext);
170 }
171
swapBuffers(RenderingThread * thread,const ClientHandle & surface)172 int Renderer::swapBuffers(RenderingThread *thread,
173 const ClientHandle &surface)
174 {
175 android::Mutex::Autolock(this->m_mutex);
176
177 SurfaceMap::iterator s = m_surfaces.find(surface);
178 if (s == m_surfaces.end()) {
179 fprintf(stderr, "swapping buffers for non existing surface\n");
180 return -1;
181 }
182 return eglSwapBuffers(m_dpy, s->second->eglSurface());
183 }
184