Home | History | Annotate | Download | only in virglrenderer
      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 
     48 static void incRefANWB(android_native_base_t* base) {
     49     ANativeWindowBuffer* anwb = reinterpret_cast<ANativeWindowBuffer*>(base);
     50     anwb->layerCount++;
     51 }
     52 
     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 {
     62     FakeANativeWindowBuffer() {
     63         ANativeWindowBuffer();
     64 
     65         common.incRef = incRefANWB;
     66         common.decRef = decRefANWB;
     67         layerCount = 0U;
     68     }
     69 };
     70 
     71 static void incRefANW(android_native_base_t* base) {
     72     ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(base);
     73     anw->oem[0]++;
     74 }
     75 
     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 
     85 static int setSwapInterval(ANativeWindow*, int) {
     86     printf("%s: not implemented\n", __func__);
     87     return 0;
     88 }
     89 
     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 
     98 static int lockBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
     99     printf("%s: not implemented\n", __func__);
    100     return 0;
    101 }
    102 
    103 static int queueBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
    104     printf("%s: not implemented\n", __func__);
    105     return 0;
    106 }
    107 
    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 
    119 static int perform(ANativeWindow*, int, ...) {
    120     printf("%s: not implemented\n", __func__);
    121     return 0;
    122 }
    123 
    124 static int cancelBuffer_DEPRECATED(ANativeWindow*, ANativeWindowBuffer*) {
    125     printf("%s: not implemented\n", __func__);
    126     return 0;
    127 }
    128 
    129 static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) {
    130     *fenceFd = -1;
    131     return dequeueBuffer_DEPRECATED(window, buffer);
    132 }
    133 
    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 
    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 {
    147     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 
    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 
    210 static GLint rcGetRendererVersion() {
    211     return 1;  // seems to be hard-coded
    212 }
    213 
    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 
    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 
    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 
    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 
    305 static EGLint rcGetNumConfigs(uint32_t* numAttribs) {
    306     *numAttribs = EglConfig::kNumAttribs;
    307     return EglConfig::vec.size();
    308 }
    309 
    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 
    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 
    359 static EGLint rcGetFBParam(EGLint) {
    360     printf("%s: not implemented\n", __func__);
    361     return 0;
    362 }
    363 
    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 
    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 
    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 
    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 
    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 
    478 static void rcOpenColorBuffer(uint32_t) {
    479     printf("%s: not implemented\n", __func__);
    480 }
    481 
    482 static void rcCloseColorBuffer(uint32_t) {
    483     printf("%s: not implemented\n", __func__);
    484 }
    485 
    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 
    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 
    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 
    600 static void rcFBPost(uint32_t) {
    601     printf("%s: not implemented\n", __func__);
    602 }
    603 
    604 static void rcFBSetSwapInterval(void* ctx_, EGLint interval) {
    605     RenderControl* rc = static_cast<RenderControl*>(ctx_);
    606     s_egl.eglSwapInterval(rc->dpy, interval);
    607 }
    608 
    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 
    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 
    685 static EGLint rcColorBufferCacheFlush(uint32_t, EGLint, int) {
    686     printf("%s: not implemented\n", __func__);
    687     return 0;
    688 }
    689 
    690 static void rcReadColorBuffer(uint32_t, GLint, GLint, GLint, GLint, GLenum, GLenum, void*) {
    691     printf("%s: not implemented\n", __func__);
    692 }
    693 
    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 
    699 static int rcOpenColorBuffer2(uint32_t) {
    700     printf("%s: not implemented\n", __func__);
    701     return 0;
    702 }
    703 
    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 
    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 
    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 
    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 
    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 
    773 static void rcFlushWindowColorBufferAsync(uint32_t windowSurface) {
    774     // No-op
    775 }
    776 
    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 
    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 
    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 
    809 static uint32_t rcCreateColorBufferDMA(uint32_t, uint32_t, GLenum, int) {
    810     printf("%s: not implemented\n", __func__);
    811     return 0U;
    812 }
    813 
    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 
    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