1 /*
2  * Copyright (C) 2018 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 #undef NDEBUG
17 
18 #include "Context.h"
19 #include "EglConfig.h"
20 #include "EglContext.h"
21 #include "EglImage.h"
22 #include "EglSurface.h"
23 #include "EglSync.h"
24 
25 #include <cassert>
26 #include <cerrno>
27 #include <cstring>
28 #include <string>
29 
30 #include <unistd.h>
31 
32 #include <GLES/gl.h>
33 #include <GLES/glext.h>
34 
35 #include <OpenGLESDispatch/EGLDispatch.h>
36 #include <OpenGLESDispatch/GLESv1Dispatch.h>
37 #include <OpenGLESDispatch/GLESv3Dispatch.h>
38 
39 #include "virgl_hw.h"
40 
41 #include "RenderControl.h"
42 
43 #include <hardware/gralloc.h>
44 #include <hardware/gralloc1.h>
45 #include <nativebase/nativebase.h>
46 #include <system/window.h>
47 
incRefANWB(android_native_base_t * base)48 static void incRefANWB(android_native_base_t* base) {
49     ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base);
50     anwb->layerCount++;
51 }
52 
decRefANWB(android_native_base_t * base)53 static void decRefANWB(android_native_base_t* base) {
54     ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base);
55     if (anwb->layerCount > 0) {
56         anwb->layerCount--;
57         if (anwb->layerCount == 0)
58             delete anwb;
59     }
60 }
61 struct FakeANativeWindowBuffer : public ANativeWindowBuffer {
FakeANativeWindowBufferFakeANativeWindowBuffer62     FakeANativeWindowBuffer() {
63         ANativeWindowBuffer();
64 
65         common.incRef = incRefANWB;
66         common.decRef = decRefANWB;
67         layerCount = 0U;
68     }
69 };
70 
incRefANW(android_native_base_t * base)71 static void incRefANW(android_native_base_t* base) {
72     ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base);
73     anw->oem[0]++;
74 }
75 
decRefANW(android_native_base_t * base)76 static void decRefANW(android_native_base_t* base) {
77     ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base);
78     if (anw->oem[0] > 0) {
79         anw->oem[0]--;
80         if (anw->oem[0] == 0)
81             delete anw;
82     }
83 }
84 
setSwapInterval(ANativeWindow *,int)85 static int setSwapInterval(ANativeWindow*, int) {
86     printf("%s: not implemented\n", __func__);
87     return 0;
88 }
89 
dequeueBuffer_DEPRECATED(ANativeWindow * window,ANativeWindowBuffer ** buffer)90 static int dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer) {
91     if (!window->oem[1])
92         return -EINVAL;
93     *buffer = reinterpret_cast<ANativeWindowBuffer*>(window->oem[1]);
94     window->oem[1] = 0;
95     return 0;
96 }
97 
lockBuffer_DEPRECATED(ANativeWindow *,ANativeWindowBuffer *)98 static int lockBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
99     printf("%s: not implemented\n", __func__);
100     return 0;
101 }
102 
queueBuffer_DEPRECATED(ANativeWindow *,ANativeWindowBuffer *)103 static int queueBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
104     printf("%s: not implemented\n", __func__);
105     return 0;
106 }
107 
query(const ANativeWindow * window,int what,int * value)108 static int query(const ANativeWindow* window, int what, int* value) {
109     switch (what) {
110         case NATIVE_WINDOW_WIDTH:
111             return static_cast<int>(window->oem[2]);
112         case NATIVE_WINDOW_HEIGHT:
113             return static_cast<int>(window->oem[3]);
114         default:
115             return -EINVAL;
116     }
117 }
118 
perform(ANativeWindow *,int,...)119 static int perform(ANativeWindow*, int, ...) {
120     printf("%s: not implemented\n", __func__);
121     return 0;
122 }
123 
cancelBuffer_DEPRECATED(ANativeWindow *,ANativeWindowBuffer *)124 static int cancelBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
125     printf("%s: not implemented\n", __func__);
126     return 0;
127 }
128 
dequeueBuffer(ANativeWindow * window,ANativeWindowBuffer ** buffer,int * fenceFd)129 static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
130     *fenceFd = -1;
131     return dequeueBuffer_DEPRECATED(window, buffer);
132 }
133 
queueBuffer(ANativeWindow * window,ANativeWindowBuffer * buffer,int fenceFd)134 static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
135     if (fenceFd >= 0)
136         close(fenceFd);
137     return queueBuffer_DEPRECATED(window, buffer);
138 }
139 
cancelBuffer(ANativeWindow * window,ANativeWindowBuffer * buffer,int fenceFd)140 static int cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) {
141     if (fenceFd >= 0)
142         close(fenceFd);
143     return cancelBuffer_DEPRECATED(window, buffer);
144 }
145 
146 struct FakeANativeWindow : public ANativeWindow {
FakeANativeWindowFakeANativeWindow147     FakeANativeWindow(uint32_t width, uint32_t height) {
148         ANativeWindow();
149 
150         common.incRef = incRefANW;
151         common.decRef = decRefANW;
152         oem[0] = 0;
153         oem[2] = static_cast<intptr_t>(width);
154         oem[3] = static_cast<intptr_t>(height);
155 
156         this->setSwapInterval = ::setSwapInterval;
157         this->dequeueBuffer_DEPRECATED = ::dequeueBuffer_DEPRECATED;
158         this->lockBuffer_DEPRECATED = ::lockBuffer_DEPRECATED;
159         this->queueBuffer_DEPRECATED = ::queueBuffer_DEPRECATED;
160         this->query = ::query;
161         this->perform = ::perform;
162         this->cancelBuffer_DEPRECATED = ::cancelBuffer_DEPRECATED;
163         this->dequeueBuffer = ::dequeueBuffer;
164         this->queueBuffer = ::queueBuffer;
165         this->cancelBuffer = ::cancelBuffer;
166     }
167 };
168 
169 // Helpers
170 
resourceToANWB(Resource * res)171 static ANativeWindowBuffer* resourceToANWB(Resource* res) {
172     ANativeWindowBuffer* buffer = new (std::nothrow) FakeANativeWindowBuffer();
173     if (!buffer)
174         return nullptr;
175 
176     buffer->width = res->args.width;
177     buffer->height = res->args.height;
178     buffer->stride = res->args.width;
179     buffer->handle = reinterpret_cast<const native_handle_t*>(res->args.handle);
180     buffer->usage_deprecated = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
181                                GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER;
182     buffer->usage =
183         GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN | GRALLOC1_CONSUMER_USAGE_CPU_WRITE_OFTEN |
184         GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE | GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN |
185         GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN | GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
186 
187     switch (res->args.format) {
188         case VIRGL_FORMAT_B8G8R8A8_UNORM:
189             buffer->format = HAL_PIXEL_FORMAT_BGRA_8888;
190             break;
191         case VIRGL_FORMAT_B5G6R5_UNORM:
192             buffer->format = HAL_PIXEL_FORMAT_RGB_565;
193             break;
194         case VIRGL_FORMAT_R8G8B8A8_UNORM:
195             buffer->format = HAL_PIXEL_FORMAT_RGBA_8888;
196             break;
197         case VIRGL_FORMAT_R8G8B8X8_UNORM:
198             buffer->format = HAL_PIXEL_FORMAT_RGBX_8888;
199             break;
200         default:
201             delete buffer;
202             return nullptr;
203     }
204 
205     return buffer;
206 }
207 
208 // RenderControl
209 
rcGetRendererVersion()210 static GLint rcGetRendererVersion() {
211     return 1;  // seems to be hard-coded
212 }
213 
rcGetEGLVersion(void * ctx_,EGLint * major,EGLint * minor)214 static EGLint rcGetEGLVersion(void* ctx_, EGLint* major, EGLint* minor) {
215     RenderControl* rc = static_cast<RenderControl*>(ctx_);
216     return s_egl.eglInitialize(rc->dpy, major, minor);
217 }
218 
rcQueryEGLString(void * ctx_,EGLenum name,void * buffer,EGLint bufferSize)219 static EGLint rcQueryEGLString(void* ctx_, EGLenum name, void* buffer, EGLint bufferSize) {
220     RenderControl* rc = static_cast<RenderControl*>(ctx_);
221     const char* str = s_egl.eglQueryString(rc->dpy, name);
222     if (!str)
223         str = "";
224 
225     if (strlen(str) > (size_t)bufferSize) {
226         memset(buffer, 0, bufferSize);
227         return -strlen(str);
228     }
229 
230     char* strOut = static_cast<char*>(buffer);
231     strncpy(strOut, str, bufferSize - 1);
232     strOut[bufferSize - 1] = 0;
233 
234     return strlen(strOut) + 1U;
235 }
236 
replaceESVersionString(const std::string & prev,const char * const newver)237 static std::string replaceESVersionString(const std::string& prev, const char* const newver) {
238     // Do not touch ES 1.x contexts (they will all be 1.1 anyway)
239     if (prev.find("ES-CM") != std::string::npos)
240         return prev;
241 
242     size_t esStart = prev.find("ES ");
243     size_t esEnd = prev.find(" ", esStart + 3);
244 
245     // Do not change out-of-spec version strings.
246     if (esStart == std::string::npos || esEnd == std::string::npos)
247         return prev;
248 
249     std::string res = prev.substr(0, esStart + 3);
250     res += newver;
251     res += prev.substr(esEnd);
252     return res;
253 }
254 
rcGetGLString(void * ctx_,EGLenum name,void * buffer,EGLint bufferSize)255 static EGLint rcGetGLString(void* ctx_, EGLenum name, void* buffer, EGLint bufferSize) {
256     std::string glStr;
257 
258     RenderControl* rc = static_cast<RenderControl*>(ctx_);
259     if (rc->ctx->ctx) {
260         const char* str = nullptr;
261         switch (rc->ctx->ctx->api) {
262             case EglContext::GLESApi::GLESApi_CM:
263                 str = reinterpret_cast<const char*>(s_gles1.glGetString(name));
264                 break;
265             default:
266                 str = reinterpret_cast<const char*>(s_gles3.glGetString(name));
267                 break;
268         }
269         if (str)
270             glStr += str;
271     }
272 
273     // FIXME: Should probably filter the extensions list like the emulator
274     //        does. We need to handle ES2 on ES3 compatibility for older
275     //        Android versions, as well as filter out unsupported features.
276 
277     if (name == GL_EXTENSIONS) {
278         glStr += ChecksumCalculator::getMaxVersionStr();
279         glStr += " ";
280 
281         // FIXME: Hard-coded to 3.0 for now. We should attempt to detect 3.1.
282         glStr += "ANDROID_EMU_gles_max_version_3_0";
283         glStr += " ";
284     }
285 
286     // FIXME: Add support for async swap and the fence_sync extensions
287 
288     // We don't support GLDMA; use VIRTGPU_RESOURCE_CREATE and a combination of
289     // VIRTGPU_TRANSFER_TO_HOST and VIRTGPU_TRANSFER_FROM_HOST.
290 
291     // FIXME: Add support for 'no host error'
292 
293     if (name == GL_VERSION)
294         glStr = replaceESVersionString(glStr, "3.0");
295 
296     int nextBufferSize = glStr.size() + 1;
297 
298     if (!buffer || nextBufferSize > bufferSize)
299         return -nextBufferSize;
300 
301     snprintf((char*)buffer, nextBufferSize, "%s", glStr.c_str());
302     return nextBufferSize;
303 }
304 
rcGetNumConfigs(uint32_t * numAttribs)305 static EGLint rcGetNumConfigs(uint32_t* numAttribs) {
306     *numAttribs = EglConfig::kNumAttribs;
307     return EglConfig::vec.size();
308 }
309 
rcGetConfigs(uint32_t bufSize,GLuint * buffer)310 static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer) {
311     size_t configAttribBytes = sizeof(EglConfig::kAttribs);
312     size_t nConfigs = EglConfig::vec.size();
313     size_t sizeNeeded = configAttribBytes + nConfigs * configAttribBytes;
314 
315     if (bufSize < sizeNeeded)
316         return -sizeNeeded;
317 
318     memcpy(buffer, &EglConfig::kAttribs, configAttribBytes);
319     size_t offset = EglConfig::kNumAttribs;
320     for (auto const& config : EglConfig::vec) {
321         memcpy(&buffer[offset], config->attribs, configAttribBytes);
322         offset += EglConfig::kNumAttribs;
323     }
324 
325     return nConfigs;
326 }
327 
rcChooseConfig(void * ctx_,EGLint * attribs,uint32_t,uint32_t * config_ints,uint32_t configs_size)328 static EGLint rcChooseConfig(void* ctx_, EGLint* attribs, uint32_t, uint32_t* config_ints,
329                              uint32_t configs_size) {
330     EGLint num_config;
331     EGLConfig configs[configs_size];
332     RenderControl* rc = static_cast<RenderControl*>(ctx_);
333     EGLBoolean ret = s_egl.eglChooseConfig(rc->dpy, attribs, configs, configs_size, &num_config);
334     if (!ret)
335         num_config = 0;
336 
337     if (configs_size) {
338         for (EGLint i = 0; i < num_config; i++) {
339             config_ints[i] = ~0U;
340             EGLint config_id;
341             if (s_egl.eglGetConfigAttrib(rc->dpy, configs[i], EGL_CONFIG_ID, &config_id)) {
342                 for (size_t i = 0; i < EglConfig::vec.size(); i++) {
343                     if (EglConfig::vec[i]->attribs[4] == config_id)
344                         config_ints[i] = i;
345                 }
346             }
347             if (config_ints[i] == ~0U) {
348                 num_config = 0;
349                 break;
350             }
351         }
352         if (!num_config)
353             memset(config_ints, 0, configs_size * sizeof(uint32_t));
354     }
355 
356     return num_config;
357 }
358 
rcGetFBParam(EGLint)359 static EGLint rcGetFBParam(EGLint) {
360     printf("%s: not implemented\n", __func__);
361     return 0;
362 }
363 
rcCreateContext(void * ctx_,uint32_t config_,uint32_t share_,uint32_t glVersion)364 static uint32_t rcCreateContext(void* ctx_, uint32_t config_, uint32_t share_, uint32_t glVersion) {
365     // clang-format off
366     EGLint attrib_list[] = {
367         EGL_CONTEXT_CLIENT_VERSION,    0,
368         EGL_CONTEXT_MINOR_VERSION_KHR, 0,
369         EGL_NONE
370     };
371     // clang-format on
372     switch (glVersion) {
373         case EglContext::GLESApi::GLESApi_CM:
374             attrib_list[1] = 1;
375             attrib_list[3] = 1;
376             break;
377         case EglContext::GLESApi::GLESApi_2:
378             attrib_list[1] = 2;
379             break;
380         case EglContext::GLESApi::GLESApi_3_0:
381             attrib_list[1] = 3;
382             break;
383         case EglContext::GLESApi::GLESApi_3_1:
384             attrib_list[1] = 3;
385             attrib_list[3] = 1;
386             break;
387     }
388     if (!attrib_list[1])
389         return 0U;
390 
391     if (config_ > EglConfig::vec.size())
392         return 0U;
393     EglConfig const* config = EglConfig::vec[config_];
394 
395     EGLContext share_context = EGL_NO_CONTEXT;
396     if (share_ > 0) {
397         std::map<uint32_t, EglContext*>::iterator context_it;
398         context_it = EglContext::map.find(share_);
399         if (context_it == EglContext::map.end())
400             return 0U;
401 
402         EglContext const* share = context_it->second;
403         share_context = share->context;
404     }
405 
406     RenderControl* rc = static_cast<RenderControl*>(ctx_);
407     EGLContext context_ =
408         s_egl.eglCreateContext(rc->dpy, config->config, share_context, attrib_list);
409     if (context_ == EGL_NO_CONTEXT)
410         return 0U;
411 
412     EglContext* context = new (std::nothrow)
413         EglContext(context_, rc->ctx->handle, (enum EglContext::GLESApi)glVersion);
414     if (!context) {
415         s_egl.eglDestroyContext(rc->dpy, context_);
416         return 0U;
417     }
418 
419     return context->id;
420 }
421 
rcDestroyContext(void * ctx_,uint32_t ctx)422 static void rcDestroyContext(void* ctx_, uint32_t ctx) {
423     std::map<uint32_t, EglContext*>::iterator it;
424     it = EglContext::map.find(ctx);
425     if (it == EglContext::map.end())
426         return;
427 
428     EglContext* context = it->second;
429 
430     RenderControl* rc = static_cast<RenderControl*>(ctx_);
431     s_egl.eglDestroyContext(rc->dpy, context->context);
432     context->context = EGL_NO_CONTEXT;
433     if (context->disposable())
434         delete context;
435 }
436 
rcCreateWindowSurface(void * ctx_,uint32_t config_,uint32_t width,uint32_t height)437 static uint32_t rcCreateWindowSurface(void* ctx_, uint32_t config_, uint32_t width,
438                                       uint32_t height) {
439     if (config_ > EglConfig::vec.size())
440         return 0U;
441 
442     EglConfig const* config = EglConfig::vec[config_];
443 
444     RenderControl* rc = static_cast<RenderControl*>(ctx_);
445     EglSurface* surface =
446         new (std::nothrow) EglSurface(config->config, rc->ctx->handle, width, height);
447     if (!surface)
448         return 0U;
449 
450     return surface->id;
451 }
452 
rcDestroyWindowSurface(void * ctx_,uint32_t surface_)453 static void rcDestroyWindowSurface(void* ctx_, uint32_t surface_) {
454     std::map<uint32_t, EglSurface*>::iterator it;
455     it = EglSurface::map.find(surface_);
456     if (it == EglSurface::map.end())
457         return;
458 
459     EglSurface* surface = it->second;
460 
461     RenderControl* rc = static_cast<RenderControl*>(ctx_);
462     s_egl.eglDestroySurface(rc->dpy, surface->surface);
463     surface->surface = EGL_NO_SURFACE;
464     if (surface->disposable()) {
465         delete surface->window;
466         delete surface;
467     }
468 }
469 
rcCreateColorBuffer(uint32_t,uint32_t,GLenum)470 static uint32_t rcCreateColorBuffer(uint32_t, uint32_t, GLenum) {
471     // NOTE: This CreateColorBuffer implementation is a no-op which returns a
472     //       special surface ID to indicate that a pbuffer surface should be
473     //       created. This is necessary because the emulator does not create a
474     //       true pbuffer, it always creates a fake one. We don't want this.
475     return ~1U;
476 }
477 
rcOpenColorBuffer(uint32_t)478 static void rcOpenColorBuffer(uint32_t) {
479     printf("%s: not implemented\n", __func__);
480 }
481 
rcCloseColorBuffer(uint32_t)482 static void rcCloseColorBuffer(uint32_t) {
483     printf("%s: not implemented\n", __func__);
484 }
485 
rcSetWindowColorBuffer(void * ctx_,uint32_t windowSurface,uint32_t colorBuffer)486 static void rcSetWindowColorBuffer(void* ctx_, uint32_t windowSurface, uint32_t colorBuffer) {
487     std::map<uint32_t, EglSurface*>::iterator surface_it;
488     surface_it = EglSurface::map.find(windowSurface);
489     if (surface_it == EglSurface::map.end())
490         return;
491 
492     EglSurface* surface = surface_it->second;
493 
494     RenderControl* rc = static_cast<RenderControl*>(ctx_);
495 
496     if (colorBuffer == ~1U) {
497         EGLint const attrib_list[] = { EGL_WIDTH, (EGLint)surface->width, EGL_HEIGHT,
498                                        (EGLint)surface->height, EGL_NONE };
499         assert(surface->surface == EGL_NO_SURFACE && "Pbuffer set twice");
500         surface->surface = s_egl.eglCreatePbufferSurface(rc->dpy, surface->config, attrib_list);
501     } else {
502         std::map<uint32_t, Resource*>::iterator resource_it;
503         resource_it = Resource::map.find(colorBuffer);
504         if (resource_it == Resource::map.end())
505             return;
506 
507         Resource* res = resource_it->second;
508         ANativeWindowBuffer* buffer = resourceToANWB(res);
509         if (!buffer)
510             return;
511 
512         if (surface->surface == EGL_NO_SURFACE) {
513             surface->window =
514                 new (std::nothrow) FakeANativeWindow(res->args.width, res->args.height);
515             if (!surface->window)
516                 return;
517 
518             NativeWindowType native_window = reinterpret_cast<NativeWindowType>(surface->window);
519             surface->window->oem[1] = (intptr_t)buffer;
520             surface->surface =
521                 s_egl.eglCreateWindowSurface(rc->dpy, surface->config, native_window, nullptr);
522         } else {
523             surface->window->oem[1] = (intptr_t)buffer;
524             s_egl.eglSwapBuffers(rc->dpy, surface->surface);
525         }
526     }
527 }
528 
rcFlushWindowColorBuffer(uint32_t windowSurface)529 static int rcFlushWindowColorBuffer(uint32_t windowSurface) {
530     std::map<uint32_t, EglSurface*>::iterator it;
531     it = EglSurface::map.find(windowSurface);
532     return it == EglSurface::map.end() ? -1 : 0;
533 }
534 
rcMakeCurrent(void * ctx_,uint32_t context_,uint32_t drawSurf,uint32_t readSurf)535 static EGLint rcMakeCurrent(void* ctx_, uint32_t context_, uint32_t drawSurf, uint32_t readSurf) {
536     std::map<uint32_t, EglContext*>::iterator context_it;
537     context_it = EglContext::map.find(context_);
538     if (context_it == EglContext::map.end())
539         return EGL_FALSE;
540 
541     EglContext* context = context_it->second;
542 
543     std::map<uint32_t, EglSurface*>::iterator surface_it;
544     surface_it = EglSurface::map.find(drawSurf);
545     if (surface_it == EglSurface::map.end())
546         return EGL_FALSE;
547 
548     EglSurface* draw_surface = surface_it->second;
549 
550     surface_it = EglSurface::map.find(readSurf);
551     if (surface_it == EglSurface::map.end())
552         return EGL_FALSE;
553 
554     EglSurface* read_surface = surface_it->second;
555 
556     RenderControl* rc = static_cast<RenderControl*>(ctx_);
557 
558     EglSurface* old_draw_surface = draw_surface->bind(rc->ctx->handle, false);
559     if (old_draw_surface)
560         old_draw_surface->unbind(false);
561 
562     EglSurface* old_read_surface = read_surface->bind(rc->ctx->handle, true);
563     if (old_read_surface)
564         old_read_surface->unbind(true);
565 
566     EglContext* old_context = context->bind(rc->ctx->handle);
567     if (old_context)
568         old_context->unbind();
569 
570     EGLBoolean ret = s_egl.eglMakeCurrent(rc->dpy, draw_surface->surface, read_surface->surface,
571                                           context->context);
572     if (!ret) {
573         // If eglMakeCurrent fails, it's specified *not* to have unbound the
574         // previous contexts or surfaces, but many implementations do. This bug
575         // isn't worked around here, and we just assume the implementations obey
576         // the spec.
577         context->unbind();
578         if (old_context)
579             old_context->bind(rc->ctx->handle);
580         read_surface->unbind(true);
581         if (old_read_surface)
582             old_read_surface->bind(rc->ctx->handle, true);
583         draw_surface->unbind(false);
584         if (old_draw_surface)
585             old_draw_surface->bind(rc->ctx->handle, false);
586     } else {
587         if (old_context && old_context->disposable())
588             delete old_context;
589         if (old_read_surface && old_read_surface->disposable())
590             delete old_read_surface;
591         if (old_draw_surface && old_draw_surface->disposable())
592             delete old_draw_surface;
593         rc->ctx->unbind();
594         rc->ctx->bind(context);
595     }
596 
597     return (EGLint)ret;
598 }
599 
rcFBPost(uint32_t)600 static void rcFBPost(uint32_t) {
601     printf("%s: not implemented\n", __func__);
602 }
603 
rcFBSetSwapInterval(void * ctx_,EGLint interval)604 static void rcFBSetSwapInterval(void* ctx_, EGLint interval) {
605     RenderControl* rc = static_cast<RenderControl*>(ctx_);
606     s_egl.eglSwapInterval(rc->dpy, interval);
607 }
608 
rcBindTexture(void * ctx_,uint32_t colorBuffer)609 static void rcBindTexture(void* ctx_, uint32_t colorBuffer) {
610     std::map<uint32_t, Resource*>::iterator it;
611     it = Resource::map.find(colorBuffer);
612     if (it == Resource::map.end())
613         return;
614 
615     RenderControl* rc = static_cast<RenderControl*>(ctx_);
616     Resource* res = it->second;
617     if (!res->image) {
618         ANativeWindowBuffer* buffer = resourceToANWB(res);
619         if (!buffer)
620             return;
621 
622         EGLClientBuffer client_buffer = static_cast<EGLClientBuffer>(buffer);
623         EGLImageKHR image = s_egl.eglCreateImageKHR(
624             rc->dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, client_buffer, nullptr);
625         if (image == EGL_NO_IMAGE_KHR)
626             return;
627 
628         EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
629         if (!img) {
630             s_egl.eglDestroyImageKHR(rc->dpy, image);
631             return;
632         }
633 
634         // FIXME: House keeping, because we won't get asked to delete the image
635         //        object otherwise, so we need to keep a reference to it..
636         res->image = img;
637     }
638 
639     if (rc->ctx->ctx->api == EglContext::GLESApi::GLESApi_CM) {
640         // FIXME: Unconditional use of GL_TEXTURE_2D here is wrong
641         s_gles1.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, res->image->image);
642     } else {
643         // FIXME: Unconditional use of GL_TEXTURE_2D here is wrong
644         s_gles3.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, res->image->image);
645     }
646 }
647 
rcBindRenderbuffer(void * ctx_,uint32_t colorBuffer)648 static void rcBindRenderbuffer(void* ctx_, uint32_t colorBuffer) {
649     std::map<uint32_t, Resource*>::iterator it;
650     it = Resource::map.find(colorBuffer);
651     if (it == Resource::map.end())
652         return;
653 
654     RenderControl* rc = static_cast<RenderControl*>(ctx_);
655     Resource* res = it->second;
656     if (!res->image) {
657         ANativeWindowBuffer* buffer = resourceToANWB(res);
658         if (!buffer)
659             return;
660 
661         EGLClientBuffer client_buffer = static_cast<EGLClientBuffer>(buffer);
662         EGLImageKHR image = s_egl.eglCreateImageKHR(
663             rc->dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, client_buffer, nullptr);
664         if (image == EGL_NO_IMAGE_KHR)
665             return;
666 
667         EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
668         if (!img) {
669             s_egl.eglDestroyImageKHR(rc->dpy, image);
670             return;
671         }
672 
673         // FIXME: House keeping, because we won't get asked to delete the image
674         //        object otherwise, so we need to keep a reference to it..
675         res->image = img;
676     }
677 
678     if (rc->ctx->ctx->api == EglContext::GLESApi::GLESApi_CM) {
679         s_gles1.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, res->image->image);
680     } else {
681         s_gles3.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, res->image->image);
682     }
683 }
684 
rcColorBufferCacheFlush(uint32_t,EGLint,int)685 static EGLint rcColorBufferCacheFlush(uint32_t, EGLint, int) {
686     printf("%s: not implemented\n", __func__);
687     return 0;
688 }
689 
rcReadColorBuffer(uint32_t,GLint,GLint,GLint,GLint,GLenum,GLenum,void *)690 static void rcReadColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) {
691     printf("%s: not implemented\n", __func__);
692 }
693 
rcUpdateColorBuffer(uint32_t,GLint,GLint,GLint,GLint,GLenum,GLenum,void *)694 static int rcUpdateColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) {
695     printf("%s: not implemented\n", __func__);
696     return 0;
697 }
698 
rcOpenColorBuffer2(uint32_t)699 static int rcOpenColorBuffer2(uint32_t) {
700     printf("%s: not implemented\n", __func__);
701     return 0;
702 }
703 
rcCreateClientImage(void * ctx_,uint32_t context_,EGLenum target,GLuint buffer_)704 static uint32_t rcCreateClientImage(void* ctx_, uint32_t context_, EGLenum target, GLuint buffer_) {
705     std::map<uint32_t, EglContext*>::iterator it;
706     it = EglContext::map.find(context_);
707     if (it == EglContext::map.end())
708         return 0U;
709 
710     EglContext* context = it->second;
711 
712     RenderControl* rc = static_cast<RenderControl*>(ctx_);
713     EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(buffer_);
714     EGLImageKHR image = s_egl.eglCreateImageKHR(rc->dpy, context, target, buffer, nullptr);
715     EglImage* img = new (std::nothrow) EglImage(rc->dpy, image, s_egl.eglDestroyImageKHR);
716     if (!img) {
717         s_egl.eglDestroyImageKHR(rc->dpy, image);
718         return 0U;
719     }
720 
721     return img->id;
722 }
723 
rcDestroyClientImage(uint32_t image_)724 static int rcDestroyClientImage(uint32_t image_) {
725     std::map<uint32_t, EglImage*>::iterator it;
726     it = EglImage::map.find(image_);
727     if (it == EglImage::map.end())
728         return EGL_FALSE;
729 
730     EglImage* image = it->second;
731 
732     delete image;
733     return EGL_TRUE;
734 }
735 
rcSelectChecksumHelper(void * ctx_,uint32_t protocol,uint32_t)736 static void rcSelectChecksumHelper(void* ctx_, uint32_t protocol, uint32_t) {
737     RenderControl* rc = static_cast<RenderControl*>(ctx_);
738     rc->ctx->checksum_calc.setVersion(protocol);
739 }
740 
rcCreateSyncKHR(void * ctx_,EGLenum type,EGLint * attribs,uint32_t,int,uint64_t * glsync_out,uint64_t * syncthread_out)741 static void rcCreateSyncKHR(void* ctx_, EGLenum type, EGLint* attribs, uint32_t, int,
742                             uint64_t* glsync_out, uint64_t* syncthread_out) {
743     *syncthread_out = 0ULL;
744 
745     RenderControl* rc = static_cast<RenderControl*>(ctx_);
746     EGLSyncKHR sync = s_egl.eglCreateSyncKHR(rc->dpy, type, attribs);
747     if (sync == EGL_NO_SYNC_KHR) {
748         *glsync_out = 0ULL;
749         return;
750     }
751 
752     EglSync* syn = new (std::nothrow) EglSync(sync);
753     if (!syn) {
754         s_egl.eglDestroySyncKHR(rc->dpy, sync);
755         *glsync_out = 0ULL;
756         return;
757     }
758 
759     *glsync_out = syn->id;
760 }
761 
rcClientWaitSyncKHR(void * ctx_,uint64_t sync_,EGLint flags,uint64_t timeout)762 static EGLint rcClientWaitSyncKHR(void* ctx_, uint64_t sync_, EGLint flags, uint64_t timeout) {
763     std::map<uint64_t, EglSync*>::iterator it;
764     it = EglSync::map.find(sync_);
765     if (it == EglSync::map.end())
766         return EGL_CONDITION_SATISFIED_KHR;
767 
768     EglSync* sync = it->second;
769     RenderControl* rc = static_cast<RenderControl*>(ctx_);
770     return s_egl.eglClientWaitSyncKHR(rc->dpy, sync->sync, flags, timeout);
771 }
772 
rcFlushWindowColorBufferAsync(uint32_t windowSurface)773 static void rcFlushWindowColorBufferAsync(uint32_t windowSurface) {
774     // No-op
775 }
776 
rcDestroySyncKHR(void * ctx_,uint64_t sync_)777 static int rcDestroySyncKHR(void* ctx_, uint64_t sync_) {
778     std::map<uint64_t, EglSync*>::iterator it;
779     it = EglSync::map.find(sync_);
780     if (it == EglSync::map.end())
781         return EGL_FALSE;
782 
783     EglSync* sync = it->second;
784     RenderControl* rc = static_cast<RenderControl*>(ctx_);
785     return s_egl.eglDestroySyncKHR(rc->dpy, sync->sync);
786 }
787 
rcSetPuid(void * ctx_,uint64_t proto)788 static void rcSetPuid(void* ctx_, uint64_t proto) {
789     union {
790         uint64_t proto;
791         struct {
792             int pid;
793             int tid;
794         } id;
795     } puid;
796 
797     puid.proto = proto;
798 
799     RenderControl* rc = static_cast<RenderControl*>(ctx_);
800     rc->ctx->setPidTid(puid.id.pid, puid.id.tid);
801 }
802 
rcUpdateColorBufferDMA(uint32_t,GLint,GLint,GLint,GLint,GLenum,GLenum,void *,uint32_t)803 static int rcUpdateColorBufferDMA(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*,
804                                   uint32_t) {
805     printf("%s: not implemented\n", __func__);
806     return 0;
807 }
808 
rcCreateColorBufferDMA(uint32_t,uint32_t,GLenum,int)809 static uint32_t rcCreateColorBufferDMA(uint32_t, uint32_t, GLenum, int) {
810     printf("%s: not implemented\n", __func__);
811     return 0U;
812 }
813 
rcWaitSyncKHR(void * ctx_,uint64_t sync_,EGLint flags)814 static void rcWaitSyncKHR(void* ctx_, uint64_t sync_, EGLint flags) {
815     std::map<uint64_t, EglSync*>::iterator it;
816     it = EglSync::map.find(sync_);
817     if (it == EglSync::map.end())
818         return;
819 
820     EglSync* sync = it->second;
821     RenderControl* rc = static_cast<RenderControl*>(ctx_);
822     // FIXME: No eglWaitSyncKHR support in SwiftShader
823     //        This call will BLOCK when it should be asynchronous!
824     s_egl.eglClientWaitSyncKHR(rc->dpy, sync->sync, flags, EGL_FOREVER_KHR);
825 }
826 
RenderControl(Context * ctx_,EGLDisplay dpy_)827 RenderControl::RenderControl(Context* ctx_, EGLDisplay dpy_) {
828     rcGetRendererVersion = ::rcGetRendererVersion;
829     rcGetEGLVersion_dec = ::rcGetEGLVersion;
830     rcQueryEGLString_dec = ::rcQueryEGLString;
831     rcGetGLString_dec = ::rcGetGLString;
832     rcGetNumConfigs = ::rcGetNumConfigs;
833     rcGetConfigs = ::rcGetConfigs;
834     rcChooseConfig_dec = ::rcChooseConfig;
835     rcGetFBParam = ::rcGetFBParam;
836     rcCreateContext_dec = ::rcCreateContext;
837     rcDestroyContext_dec = ::rcDestroyContext;
838     rcCreateWindowSurface_dec = ::rcCreateWindowSurface;
839     rcDestroyWindowSurface_dec = ::rcDestroyWindowSurface;
840     rcCreateColorBuffer = ::rcCreateColorBuffer;
841     rcOpenColorBuffer = ::rcOpenColorBuffer;
842     rcCloseColorBuffer = ::rcCloseColorBuffer;
843     rcSetWindowColorBuffer_dec = ::rcSetWindowColorBuffer;
844     rcFlushWindowColorBuffer = ::rcFlushWindowColorBuffer;
845     rcMakeCurrent_dec = ::rcMakeCurrent;
846     rcFBPost = ::rcFBPost;
847     rcFBSetSwapInterval_dec = ::rcFBSetSwapInterval;
848     rcBindTexture_dec = ::rcBindTexture;
849     rcBindRenderbuffer_dec = ::rcBindRenderbuffer;
850     rcColorBufferCacheFlush = ::rcColorBufferCacheFlush;
851     rcReadColorBuffer = ::rcReadColorBuffer;
852     rcUpdateColorBuffer = ::rcUpdateColorBuffer;
853     rcOpenColorBuffer2 = ::rcOpenColorBuffer2;
854     rcCreateClientImage_dec = ::rcCreateClientImage;
855     rcDestroyClientImage = ::rcDestroyClientImage;
856     rcSelectChecksumHelper_dec = ::rcSelectChecksumHelper;
857     rcCreateSyncKHR_dec = ::rcCreateSyncKHR;
858     rcClientWaitSyncKHR_dec = ::rcClientWaitSyncKHR;
859     rcFlushWindowColorBufferAsync = ::rcFlushWindowColorBufferAsync;
860     rcDestroySyncKHR_dec = ::rcDestroySyncKHR;
861     rcSetPuid_dec = ::rcSetPuid;
862     rcUpdateColorBufferDMA = ::rcUpdateColorBufferDMA;
863     rcCreateColorBufferDMA = ::rcCreateColorBufferDMA;
864     rcWaitSyncKHR_dec = ::rcWaitSyncKHR;
865 
866     dpy = dpy_;
867     ctx = ctx_;
868 }
869