/* * Copyright (C) 2011 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 "RenderControl.h" #include "DispatchTables.h" #include "FbConfig.h" #include "FrameBuffer.h" #include "RenderThreadInfo.h" #include "ChecksumCalculatorThreadInfo.h" #include "OpenGLESDispatch/EGLDispatch.h" static const GLint rendererVersion = 1; static GLint rcGetRendererVersion() { return rendererVersion; } static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return EGL_FALSE; } *major = (EGLint)fb->getCaps().eglMajor; *minor = (EGLint)fb->getCaps().eglMinor; return EGL_TRUE; } static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; } const char *str = s_egl.eglQueryString(fb->getDisplay(), name); if (!str) { return 0; } int len = strlen(str) + 1; if (!buffer || len > bufferSize) { return -len; } strcpy((char *)buffer, str); return len; } static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) { RenderThreadInfo *tInfo = RenderThreadInfo::get(); const char *str = NULL; int len = 0; if (tInfo && tInfo->currContext.Ptr()) { if (tInfo->currContext->isGL2()) { str = (const char *)s_gles2.glGetString(name); } else { str = (const char *)s_gles1.glGetString(name); } if (str) { len = strlen(str) + 1; } } // We add the maximum supported GL protocol number into GL_EXTENSIONS const char* glProtocolStr = NULL; if (name == GL_EXTENSIONS) { glProtocolStr = ChecksumCalculatorThreadInfo::getMaxVersionString(); if (len==0) len = 1; // the last byte len += strlen(glProtocolStr) + 1; } if (name = GL_VERSION) { // We're forcing version 2.0 no matter what the host provides as // our emulation layer isn't prepared for anything newer (yet). // This goes in parallel with filtering the extension set for // any unwanted extensions. If we don't force the right version // here certain parts of the system will assume API conditions // which aren't met. static const char *version = "OpenGL ES 2.0"; str = version; len = strlen(str) + 1; } if (!buffer || len > bufferSize) { return -len; } if (name == GL_EXTENSIONS) { snprintf((char *)buffer, bufferSize, "%s%s ", str ? str : "", glProtocolStr); } else if (str) { strcpy((char *)buffer, str); } else { if (bufferSize >= 1) { ((char*)buffer)[0] = '\0'; } len = 0; } return len; } static EGLint rcGetNumConfigs(uint32_t* p_numAttribs) { int numConfigs = 0, numAttribs = 0; FrameBuffer::getFB()->getConfigs()->getPackInfo(&numConfigs, &numAttribs); if (p_numAttribs) { *p_numAttribs = static_cast(numAttribs); } return numConfigs; } static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer) { GLuint bufferSize = (GLuint)bufSize; return FrameBuffer::getFB()->getConfigs()->packConfigs(bufferSize, buffer); } static EGLint rcChooseConfig(EGLint *attribs, uint32_t attribs_size, uint32_t *configs, uint32_t configs_size) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb || attribs_size==0) { return 0; } return fb->getConfigs()->chooseConfig( attribs, (EGLint*)configs, (EGLint)configs_size); } static EGLint rcGetFBParam(EGLint param) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; } EGLint ret = 0; switch(param) { case FB_WIDTH: ret = fb->getWidth(); break; case FB_HEIGHT: ret = fb->getHeight(); break; case FB_XDPI: ret = 72; // XXX: should be implemented break; case FB_YDPI: ret = 72; // XXX: should be implemented break; case FB_FPS: ret = 60; break; case FB_MIN_SWAP_INTERVAL: ret = 1; // XXX: should be implemented break; case FB_MAX_SWAP_INTERVAL: ret = 1; // XXX: should be implemented break; default: break; } return ret; } static uint32_t rcCreateContext(uint32_t config, uint32_t share, uint32_t glVersion) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; } // To make it consistent with the guest, create GLES2 context when GL // version==2 or 3 HandleType ret = fb->createRenderContext(config, share, glVersion == 2 || glVersion == 3); return ret; } static void rcDestroyContext(uint32_t context) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->DestroyRenderContext(context); } static uint32_t rcCreateWindowSurface(uint32_t config, uint32_t width, uint32_t height) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; } return fb->createWindowSurface(config, width, height); } static void rcDestroyWindowSurface(uint32_t windowSurface) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->DestroyWindowSurface( windowSurface ); } static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height, GLenum internalFormat) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; } return fb->createColorBuffer(width, height, internalFormat); } static int rcOpenColorBuffer2(uint32_t colorbuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return -1; } return fb->openColorBuffer( colorbuffer ); } // Deprecated, kept for compatibility with old system images only. // Use rcOpenColorBuffer2 instead. static void rcOpenColorBuffer(uint32_t colorbuffer) { (void) rcOpenColorBuffer2(colorbuffer); } static void rcCloseColorBuffer(uint32_t colorbuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->closeColorBuffer( colorbuffer ); } static int rcFlushWindowColorBuffer(uint32_t windowSurface) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return -1; } if (!fb->flushWindowSurfaceColorBuffer(windowSurface)) { return -1; } return 0; } static void rcSetWindowColorBuffer(uint32_t windowSurface, uint32_t colorBuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->setWindowSurfaceColorBuffer(windowSurface, colorBuffer); } static EGLint rcMakeCurrent(uint32_t context, uint32_t drawSurf, uint32_t readSurf) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return EGL_FALSE; } bool ret = fb->bindContext(context, drawSurf, readSurf); return (ret ? EGL_TRUE : EGL_FALSE); } static void rcFBPost(uint32_t colorBuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->post(colorBuffer); } static void rcFBSetSwapInterval(EGLint interval) { // XXX: TBD - should be implemented } static void rcBindTexture(uint32_t colorBuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->bindColorBufferToTexture(colorBuffer); } static void rcBindRenderbuffer(uint32_t colorBuffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->bindColorBufferToRenderbuffer(colorBuffer); } static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer, EGLint postCount, int forRead) { // XXX: TBD - should be implemented return 0; } static void rcReadColorBuffer(uint32_t colorBuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return; } fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels); } static int rcUpdateColorBuffer(uint32_t colorBuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void* pixels) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return -1; } fb->updateColorBuffer(colorBuffer, x, y, width, height, format, type, pixels); return 0; } static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buffer) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; } return fb->createClientImage(context, target, buffer); } static int rcDestroyClientImage(uint32_t image) { FrameBuffer *fb = FrameBuffer::getFB(); if (!fb) { return 0; } return fb->destroyClientImage(image); } static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t reserved) { ChecksumCalculatorThreadInfo::setVersion(protocol); } void initRenderControlContext(renderControl_decoder_context_t *dec) { dec->rcGetRendererVersion = rcGetRendererVersion; dec->rcGetEGLVersion = rcGetEGLVersion; dec->rcQueryEGLString = rcQueryEGLString; dec->rcGetGLString = rcGetGLString; dec->rcGetNumConfigs = rcGetNumConfigs; dec->rcGetConfigs = rcGetConfigs; dec->rcChooseConfig = rcChooseConfig; dec->rcGetFBParam = rcGetFBParam; dec->rcCreateContext = rcCreateContext; dec->rcDestroyContext = rcDestroyContext; dec->rcCreateWindowSurface = rcCreateWindowSurface; dec->rcDestroyWindowSurface = rcDestroyWindowSurface; dec->rcCreateColorBuffer = rcCreateColorBuffer; dec->rcOpenColorBuffer = rcOpenColorBuffer; dec->rcCloseColorBuffer = rcCloseColorBuffer; dec->rcSetWindowColorBuffer = rcSetWindowColorBuffer; dec->rcFlushWindowColorBuffer = rcFlushWindowColorBuffer; dec->rcMakeCurrent = rcMakeCurrent; dec->rcFBPost = rcFBPost; dec->rcFBSetSwapInterval = rcFBSetSwapInterval; dec->rcBindTexture = rcBindTexture; dec->rcBindRenderbuffer = rcBindRenderbuffer; dec->rcColorBufferCacheFlush = rcColorBufferCacheFlush; dec->rcReadColorBuffer = rcReadColorBuffer; dec->rcUpdateColorBuffer = rcUpdateColorBuffer; dec->rcOpenColorBuffer2 = rcOpenColorBuffer2; dec->rcCreateClientImage = rcCreateClientImage; dec->rcDestroyClientImage = rcDestroyClientImage; dec->rcSelectChecksumCalculator = rcSelectChecksumCalculator; }