• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "RenderingThread.h"
26 
27 #include "ANPNativeWindow_npapi.h"
28 
29 extern ANPLogInterfaceV0           gLogI;
30 extern ANPNativeWindowInterfaceV0  gNativeWindowI;
31 
RenderingThread(NPP npp)32 RenderingThread::RenderingThread(NPP npp) : android::Thread() {
33     m_npp = npp;
34     m_width = -1;
35     m_height = -1;
36 
37     m_ANW = NULL;
38 #if (!USE_SOFTWARE_RENDERING)
39     m_eglSurface = EGL_NO_SURFACE;
40     m_eglContext = EGL_NO_CONTEXT;
41     m_eglDisplay = EGL_NO_DISPLAY;
42 #endif
43 }
44 
readyToRun()45 android::status_t RenderingThread::readyToRun() {
46     gLogI.log(kError_ANPLogType, "thread %p acquiring native window...", this);
47     while (m_ANW == NULL) {
48         m_ANW = gNativeWindowI.acquireNativeWindow(m_npp);
49         if (!m_ANW)
50             gLogI.log(kError_ANPLogType, "thread %p acquire native window FAILED!", this);
51 
52     }
53     gLogI.log(kError_ANPLogType, "thread %p acquired native window successfully!", this);
54 
55 #if (!USE_SOFTWARE_RENDERING)
56     m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
57 
58     //initialize context
59     EGLint numConfigs;
60     static const EGLint configAttribs[] = {
61         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
62         EGL_RED_SIZE, 8,
63         EGL_GREEN_SIZE, 8,
64         EGL_BLUE_SIZE, 8,
65         EGL_ALPHA_SIZE, 8,
66         EGL_NONE
67     };
68 
69     eglChooseConfig(m_eglDisplay, configAttribs, &m_eglConfig, 1, &numConfigs);
70     checkGlError("eglChooseConfig");
71 
72     static const EGLint contextAttribs[] = {
73         EGL_CONTEXT_CLIENT_VERSION, 2,
74         EGL_NONE
75     };
76 
77     m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, NULL, contextAttribs);
78     checkGlError("eglCreateContext");
79 #endif
80 
81     return android::NO_ERROR;
82 }
83 
setDimensions(int width,int height)84 void RenderingThread::setDimensions(int width, int height) {
85     android::Mutex::Autolock lock(m_sync);
86     m_width = width;
87     m_height = height;
88 }
89 
getDimensions(int & width,int & height)90 void RenderingThread::getDimensions(int& width, int& height) {
91     android::Mutex::Autolock lock(m_sync);
92     width = m_width;
93     height = m_height;
94 }
95 
printGLString(const char * name,GLenum s)96 void RenderingThread::printGLString(const char *name, GLenum s) {
97     const char *v = (const char *) glGetString(s);
98     gLogI.log(kError_ANPLogType, "GL %s = %s\n", name, v);
99 }
100 
checkGlError(const char * op)101 void RenderingThread::checkGlError(const char* op) {
102     for (GLint error = glGetError(); error; error
103             = glGetError()) {
104         gLogI.log(kError_ANPLogType, "after %s() glError (0x%x)\n", op, error);
105     }
106 }
107 
getInternalFormat(SkBitmap::Config config)108 GLenum RenderingThread::getInternalFormat(SkBitmap::Config config)
109 {
110     switch(config) {
111         case SkBitmap::kA8_Config:
112             return GL_ALPHA;
113         case SkBitmap::kARGB_4444_Config:
114             return GL_RGBA;
115         case SkBitmap::kARGB_8888_Config:
116             return GL_RGBA;
117         case SkBitmap::kRGB_565_Config:
118             return GL_RGB;
119         default:
120             return -1;
121     }
122 }
123 
getType(SkBitmap::Config config)124 GLenum RenderingThread::getType(SkBitmap::Config config)
125 {
126     switch(config) {
127         case SkBitmap::kA8_Config:
128             return GL_UNSIGNED_BYTE;
129         case SkBitmap::kARGB_4444_Config:
130             return GL_UNSIGNED_SHORT_4_4_4_4;
131         case SkBitmap::kARGB_8888_Config:
132             return GL_UNSIGNED_BYTE;
133         case SkBitmap::kIndex8_Config:
134             return -1; // No type for compressed data.
135         case SkBitmap::kRGB_565_Config:
136             return GL_UNSIGNED_SHORT_5_6_5;
137         default:
138             return -1;
139     }
140 }
141 
setupNativeWindow(ANativeWindow * ANW,const SkBitmap & bitmap)142 void RenderingThread::setupNativeWindow(ANativeWindow* ANW, const SkBitmap& bitmap)
143 {
144     int result = ANativeWindow_setBuffersGeometry(ANW, bitmap.width(),
145             bitmap.height(), WINDOW_FORMAT_RGBA_8888);
146 
147     if (android::NO_ERROR != result) {
148         gLogI.log(kError_ANPLogType, "ERROR setBuffersGeometry() status is (%d)", result);
149     }
150 
151 #if (!USE_SOFTWARE_RENDERING)
152     if (m_eglSurface != EGL_NO_SURFACE) {
153         gLogI.log(kDebug_ANPLogType, "destroying old surface");
154         eglDestroySurface(m_eglDisplay, m_eglSurface);
155     }
156 
157     m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, ANW, NULL);
158     checkGlError("eglCreateWindowSurface");
159 
160     eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
161 
162     //optional: enable async mode
163     //eglSwapInterval(m_eglDisplay, 0);
164 #endif
165 
166     updateNativeWindow(ANW, bitmap);
167 }
168 
updateNativeWindow(ANativeWindow * ANW,const SkBitmap & bitmap)169 void RenderingThread::updateNativeWindow(ANativeWindow* ANW,
170                                          const SkBitmap& bitmap)
171 {
172 #if USE_SOFTWARE_RENDERING
173     if (bitmap.height() == 0 || bitmap.width() == 0)
174         return;
175 
176     //STEP 1: lock the ANW, getting a buffer
177     ANativeWindow_Buffer buffer;
178     if (ANativeWindow_lock(ANW, &buffer, NULL) < 0 ) // todo: use rect parameter for efficiency
179         return;
180 
181     //STEP 2: draw into the buffer
182     uint8_t* img = (uint8_t*)buffer.bits;
183     int row, col;
184     int bpp = 4; // Here we only deal with RGBA8888 format.
185     bitmap.lockPixels();
186     uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
187     // Copy line by line to handle offsets and stride
188     for (row = 0 ; row < bitmap.height(); row ++) {
189         uint8_t* dst = &(img[(buffer.stride * (row + 0) + 0) * bpp]);
190         uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
191         memcpy(dst, src, bpp * bitmap.width());
192     }
193     bitmap.unlockPixels();
194 
195     //STEP 3: push the buffer to the queue
196     ANativeWindow_unlockAndPost(ANW);
197 
198 #else
199 
200     //rotate the intensity of the green channel, other channels fixed
201     static int i = 0;
202     i = (i >= 245) ? 0 : i+10;
203 
204     glClearColor(0.6, (i*1.0/256), 0.6, 0.6);
205     glClear(GL_COLOR_BUFFER_BIT);
206 
207     eglSwapBuffers(m_eglDisplay, m_eglSurface);
208 #endif
209 }
210 
211