bool BootAnimation::android() { initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); // clear screen glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); const GLint xc = (mWidth - mAndroid[0].w) / 2; const GLint yc = (mHeight - mAndroid[0].h) / 2; const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); // draw and update only what we need mNativeWindowSurface->setSwapRectangle(updateRect.left, updateRect.top, updateRect.width(), updateRect.height()); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { nsecs_t now = systemTime(); double time = now - startTime; float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w; GLint x = xc - offset; glDisable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); if (res == EGL_FALSE) break; // 12fps: don't animate too fast to preserve CPU const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now); if (sleepTime > 0) usleep(sleepTime); } while (!exitPending()); glDeleteTextures(1, &mAndroid[0].name); glDeleteTextures(1, &mAndroid[1].name); return false; }
void draw() override { glClear(GL_COLOR_BUFFER_BIT); GLint windowWidth = getWindow()->getWidth(); GLint windowHeight = getWindow()->getHeight(); glDrawTexiOES(mX, mY, 0, mWidth, mHeight); glDrawTexiOES(windowWidth - mX, mY, 0, mWidth, mHeight); glDrawTexiOES(mX, windowHeight - mY, 0, mWidth, mHeight); glDrawTexiOES(windowWidth - mX, windowHeight - mY, 0, mWidth, mHeight); mX += mReverseX ? -1 : 1; mY += mReverseY ? -1 : 1; if (mX + mWidth >= windowWidth) mReverseX = true; if (mX < 0) mReverseX = false; if (mY + mHeight >= windowHeight) mReverseY = true; if (mY < 0) mReverseY = false; ++mWidth; ++mHeight; if (mWidth >= windowWidth) mWidth = 0; if (mHeight >= windowHeight) mHeight = 0; angle::Sleep(16); }
static int display_bitmap(PrivInfo* priv, FtkBitmap* bitmap, int x, int y, int width, int height, int xoffset, int yoffset) { GLint crop[4] = {0}; crop[0] = x; crop[1] = y; crop[2] = width; crop[3] = height; if(Android_PreRender() != RET_OK) { return 0; } glColor4f(1,1,1,1); glBindTexture(GL_TEXTURE_2D, 0); glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftk_bitmap_width(bitmap), ftk_bitmap_height(bitmap), 0, GL_RGBA, GL_UNSIGNED_BYTE, ftk_bitmap_lock(bitmap)); glDrawTexiOES(xoffset, yoffset, 0, width, height); Android_Render(); return 0; }
void video_render(long tick, int width, int height) { opengl_video_stage_config_t *config; static int num = 0; screen_width = width; screen_height = height; //glViewport(0, 0, width, height); glBindTexture(GL_TEXTURE_2D, texture); config = opengl_video_stage_get(); if (config->num_picture_decoded != num) { /* a new frame is available, update texture */ if ((config != NULL) && (config->data != NULL) && (config->num_picture_decoded > 0)) { vp_os_mutex_lock( &config->mutex ); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_WIDTH, VIDEO_HEIGHT, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, config->data ); num = config->num_picture_decoded; vp_os_mutex_unlock( &config->mutex ); } } /* and draw it on the screen */ __android_log_print( ANDROID_LOG_INFO, "ARDrone", "screen_width=%d, screen_height=%d\n", screen_width, screen_height ); glDrawTexiOES(0, 0, 0, screen_width, screen_height); }
void GLTexture::draw(int dest_x, int dest_y, unsigned dest_width, unsigned dest_height, int src_x, int src_y, unsigned src_width, unsigned src_height) const { #ifdef ANDROID const GLint rect[4] = { src_x, src_y + src_height, src_width, /* negative height to flip the texture */ -(int)src_height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect); /* glDrawTexiOES() circumvents the projection settings, thus we must roll our own translation */ glDrawTexiOES(OpenGL::translate_x + dest_x, (int)OpenGL::screen_height - OpenGL::translate_y - dest_y - (int)dest_height, 0, dest_width, dest_height); #else GLfloat x0 = (GLfloat)src_x / width; GLfloat y0 = (GLfloat)src_y / height; GLfloat x1 = (GLfloat)(src_x + src_width) / width; GLfloat y1 = (GLfloat)(src_y + src_height) / height; glBegin(GL_QUADS); glTexCoord2f(x0, y0); glVertex2i(dest_x, dest_y); glTexCoord2f(x1, y0); glVertex2i(dest_x + dest_width, dest_y); glTexCoord2f(x1, y1); glVertex2i(dest_x + dest_width, dest_y + dest_height); glTexCoord2f(x0, y1); glVertex2i(dest_x, dest_y + dest_height); glEnd(); #endif }
// 1文字を表示 void RenderGlyph(const glyph* glyphdat, int x, int y) { int box[] = { glyphdat->x + glyphdat->x_bearing, glyphdat->y, glyphdat->width + 2, glyphdat->height + 2 }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, box); glDrawTexiOES(x, y, 0, glyphdat->width + 1, glyphdat->height); glFinish(); }
// 円を描画 void drawCircle(int x, int y) { glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, texName[0]); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1, 1, 1, 1); int box[] = { 256 - 32, 128 - 32, 32, 32 }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, box); glDrawTexiOES(x - 16, y - 16, 0, 64, 64); }
void CGraphicsComponent::NativeBlitAndroid(int32_t x, int32_t y, int32_t aWidth, int32_t aHeight, int32_t cropLeft, int32_t cropTop, int32_t cropRight, int32_t cropBottom, int32_t orgWidth, int32_t orgHeight) { const bool bCrop = (cropLeft != 0) || (cropTop != 0) || (cropRight != orgWidth) || (cropBottom != orgHeight); if (bCrop) { Crop(cropLeft, cropTop, cropRight, cropBottom); } glDrawTexiOES(x, y, 0, aWidth, aHeight); if (glGetError() != 0) LOG_ERROR("Error!"); if (bCrop) { Crop(0, 0, orgWidth, orgHeight); } }
inline void GLTexture::DrawFlippedOES(PixelRect dest, PixelRect src) const { const GLint rect[4] = { src.left, src.top, (GLint)src.GetWidth(), (GLint)src.GetHeight() }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect); /* glDrawTexiOES() circumvents the projection settings, thus we must roll our own translation */ glDrawTexiOES(OpenGL::translate.x + dest.left, OpenGL::viewport_size.y - OpenGL::translate.y - dest.bottom, 0, dest.GetWidth(), dest.GetHeight()); }
inline void GLTexture::DrawFlippedOES(PixelRect dest, PixelRect src) const { const GLint rect[4] = { src.left, src.top, src.right - src.left, src.bottom - src.top }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect); /* glDrawTexiOES() circumvents the projection settings, thus we must roll our own translation */ glDrawTexiOES(OpenGL::translate.x + dest.left, OpenGL::screen_height - OpenGL::translate.y - dest.bottom, 0, dest.right - dest.left, dest.bottom - dest.top); }
void video_render(long tick, int width, int height) { static int num = 0; glBindTexture(GL_TEXTURE_2D, texture); if (num_picture_decoded != num) { /* a new frame is available, update texture */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, VIDEO_WIDTH,VIDEO_HEIGHT, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, picture_buf); num = num_picture_decoded; } /* and draw it on the screen */ glDrawTexiOES(0, 0, 0, width, height); }
void DrawTexture::run(uint32_t msTicks) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_TEXTURE_2D); glDrawArrays(GL_LINE_LOOP, 0, 4); glEnable(GL_TEXTURE_2D); glDrawTexiOES(uWidth/2 - uTexWidth/2, (uHeight)/2 - uTexHeight/2, 0, uTexWidth, uTexHeight); assert(GL_NO_ERROR == glGetError()); }
static inline void drawCharTex(GLTexture_t * tex, SDL_Rect * src, SDL_Rect * dest, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { GLint cropRect[4]; /* GLfloat texColor[4]; static const float onediv255 = 1.0f / 255.0f; */ if( !dest->h || !dest->w ) return; qglBindTexture(GL_TEXTURE_2D, tex->id); qglColor4x(r * 0x100, g * 0x100, b * 0x100, 200 * 0x100 ); //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); qglEnable(GL_BLEND); qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); #if 0 dest->x = dest->x*320/screen_width; dest->y = dest->y*200/screen_height; dest->w = dest->w*320/screen_width; dest->h = dest->h*200/screen_height; DrawQuad(dest->x, 200 - dest->y - dest->h, dest->w, dest->h, 0, 0, 1/*tex->w*/, 1/*tex->h*/); #endif cropRect[0] = 0; cropRect[1] = tex->h; cropRect[2] = tex->w; cropRect[3] = -tex->h; if(src) {//left down width hight cropRect[0] = src->x; cropRect[1] = src->h; // TODO: check if height works as expected in inverted GL coords cropRect[2] = src->w; cropRect[3] = -src->h; // TODO: check if height works as expected in inverted GL coords } qglTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); glDrawTexiOES(dest->x, screen_height - dest->y - dest->h, 0, dest->w, dest->h); }
inline void GLTexture::DrawOES(PixelScalar dest_x, PixelScalar dest_y, UPixelScalar dest_width, UPixelScalar dest_height, PixelScalar src_x, PixelScalar src_y, UPixelScalar src_width, UPixelScalar src_height) const { const GLint rect[4] = { src_x, src_y + src_height, src_width, /* negative height to flip the texture */ -(int)src_height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect); /* glDrawTexiOES() circumvents the projection settings, thus we must roll our own translation */ glDrawTexiOES(OpenGL::translate.x + dest_x, OpenGL::screen_height - OpenGL::translate.y - dest_y - dest_height, 0, dest_width, dest_height); }
static inline void drawCharTex(GLTexture_t * tex, SDL_Rect * src, SDL_Rect * dest, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { GLint cropRect[4]; /* GLfloat texColor[4]; static const float onediv255 = 1.0f / 255.0f; */ if( !dest->h || !dest->w ) return; glBindTexture(GL_TEXTURE_2D, tex->id); glColor4x(r * 0x100, g * 0x100, b * 0x100, a * 0x100 ); //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* texColor[0] = r * onediv255; texColor[1] = g * onediv255; texColor[2] = b * onediv255; texColor[3] = a * onediv255; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texColor); */ cropRect[0] = 0; cropRect[1] = tex->h; cropRect[2] = tex->w; cropRect[3] = -tex->h; if(src) { cropRect[0] = src->x; cropRect[1] = src->h; // TODO: check if height works as expected in inverted GL coords cropRect[2] = src->w; cropRect[3] = -src->h; // TODO: check if height works as expected in inverted GL coords } glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); glDrawTexiOES(dest->x, SDL_ANDROID_sWindowHeight - dest->y - dest->h, 0, dest->w, dest->h); }
/* * Class: com_mcxiaoke_ndk_Native * Method: render * Signature: (JJ)Z */ JNIEXPORT jboolean JNICALL Java_com_mcxiaoke_ndk_Native_renderOpenGL (JNIEnv *env, jclass clazz, jlong inst, jlong avi) { Instance* instance = (Instance*) inst; jboolean isFrameRead = JNI_FALSE; int keyFrame = 0; // Read AVI frame bytes to bitmap long frameSize = AVI_read_frame((avi_t*) avi, instance->buffer, &keyFrame); // Check if frame read if (0 >= frameSize) { goto exit; } // Frame read isFrameRead = JNI_TRUE; // Update the texture with the new frame glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, AVI_video_width((avi_t*) avi), AVI_video_height((avi_t*) avi), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, instance->buffer); // Draw texture glDrawTexiOES(0, 0, 0, AVI_video_width((avi_t*) avi), AVI_video_height((avi_t*) avi)); /** to fix error: glDrawTexiOES was not declared in this scope add this to Android.mk: LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES **/ exit: return isFrameRead; }
inline void GLTexture::DrawOES(int dest_x, int dest_y, unsigned dest_width, unsigned dest_height, int src_x, int src_y, unsigned src_width, unsigned src_height) const { const GLint rect[4] = { src_x, int(src_y + src_height), int(src_width), /* negative height to flip the texture */ -(int)src_height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect); /* glDrawTexiOES() circumvents the projection settings, thus we must roll our own translation */ glDrawTexiOES(OpenGL::translate.x + dest_x, OpenGL::viewport_size.y - OpenGL::translate.y - dest_y - dest_height, 0, dest_width, dest_height); }
bool BootAnimation::movie() { ZipFileRO& zip(mZip); size_t numEntries = zip.getNumEntries(); ZipEntryRO desc = zip.findEntryByName("desc.txt"); FileMap* descMap = zip.createEntryFileMap(desc); LOGE_IF(!descMap, "descMap is null"); if (!descMap) { return false; } String8 desString((char const*)descMap->getDataPtr(), descMap->getDataLength()); char const* s = desString.string(); Animation animation; // Parse the description file for (;;) { const char* endl = strstr(s, "\n"); if (!endl) break; String8 line(s, endl - s); const char* l = line.string(); int fps, width, height, count, pause; char path[256]; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { //LOGD("> w=%d, h=%d, fps=%d", fps, width, height); animation.width = width; animation.height = height; animation.fps = fps; } if (sscanf(l, "p %d %d %s", &count, &pause, path) == 3) { //LOGD("> count=%d, pause=%d, path=%s", count, pause, path); Animation::Part part; part.count = count; part.pause = pause; part.path = path; animation.parts.add(part); } s = ++endl; } // read all the data structures const size_t pcount = animation.parts.size(); for (size_t i=0 ; i<numEntries ; i++) { char name[256]; ZipEntryRO entry = zip.findEntryByIndex(i); if (zip.getEntryFileName(entry, name, 256) == 0) { const String8 entryName(name); const String8 path(entryName.getPathDir()); const String8 leaf(entryName.getPathLeaf()); if (leaf.size() > 0) { for (int j=0 ; j<pcount ; j++) { if (path == animation.parts[j].path) { int method; // supports only stored png files if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) { if (method == ZipFileRO::kCompressStored) { FileMap* map = zip.createEntryFileMap(entry); if (map) { Animation::Frame frame; frame.name = leaf; frame.map = map; Animation::Part& part(animation.parts.editItemAt(j)); part.frames.add(frame); } } } } } } } } // clear screen glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); const int xc = (mWidth - animation.width) / 2; const int yc = ((mHeight - animation.height) / 2); nsecs_t lastFrame = systemTime(); nsecs_t frameDuration = s2ns(1) / animation.fps; Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Region(Rect(xc, yc, xc+animation.width, yc+animation.height))); for (int i=0 ; i<pcount && !exitPending() ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); glBindTexture(GL_TEXTURE_2D, 0); for (int r=0 ; !part.count || r<part.count ; r++) { for (int j=0 ; j<fcount && !exitPending(); j++) { const Animation::Frame& frame(part.frames[j]); if (r > 0) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { if (part.count != 1) { glGenTextures(1, &frame.tid); glBindTexture(GL_TEXTURE_2D, frame.tid); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } initTexture( frame.map->getDataPtr(), frame.map->getDataLength()); } if (!clearReg.isEmpty()) { Rect r; Region::iterator head(clearReg); glEnable(GL_SCISSOR_TEST); while (head.iterate(&r)) { glScissor(r.left, mHeight - r.bottom, r.width(), r.height()); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } glDrawTexiOES(xc, yc, 0, animation.width, animation.height); eglSwapBuffers(mDisplay, mSurface); nsecs_t now = systemTime(); nsecs_t delay = frameDuration - (now - lastFrame); lastFrame = now; long wait = ns2us(frameDuration); if (wait > 0) usleep(wait); } usleep(part.pause * ns2us(frameDuration)); } // free the textures for this part if (part.count != 1) { for (int j=0 ; j<fcount ; j++) { const Animation::Frame& frame(part.frames[j]); glDeleteTextures(1, &frame.tid); } } } return false; }
void update_frame(uint8_t* pixels, int w, int h, int dw, int dh){ glClear(GL_COLOR_BUFFER_BIT); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGB, ARRAY_DATA_TYPE, pixels); glDrawTexiOES(dw, dh, 0, w, h); CHECK_GL_ERROR(); }
void CGraphicsComponent::NativeBlitAndroid(int32_t x, int32_t y, int32_t aWidth, int32_t aHeight) { glDrawTexiOES(x, y, 0, aWidth, aHeight); if (glGetError() != 0) LOG_ERROR("Error!"); }
void LayerBlur::onDraw(const Region& clip) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); int x = mTransformedBounds.left; int y = mTransformedBounds.top; int w = mTransformedBounds.width(); int h = mTransformedBounds.height(); GLint X = x; GLint Y = fbHeight - (y + h); if (X < 0) { w += X; X = 0; } if (Y < 0) { h += Y; Y = 0; } if (w<0 || h<0) { // we're outside of the framebuffer return; } if (mTextureName == -1U) { // create the texture name the first time // can't do that in the ctor, because it runs in another thread. glGenTextures(1, &mTextureName); } Region::iterator iterator(clip); if (iterator) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mTextureName); if (mRefreshCache) { mRefreshCache = false; mAutoRefreshPending = false; // allocate enough memory for 4-bytes (2 pixels) aligned data const int32_t s = (w + 1) & ~1; uint16_t* const pixels = (uint16_t*)malloc(s*h*2); // This reads the frame-buffer, so a h/w GL would have to // finish() its rendering first. we don't want to do that // too often. Read data is 4-bytes aligned. glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); // blur that texture. GGLSurface bl; bl.version = sizeof(GGLSurface); bl.width = w; bl.height = h; bl.stride = s; bl.format = GGL_PIXEL_FORMAT_RGB_565; bl.data = (GGLubyte*)pixels; blurFilter(&bl, 8, 2); // NOTE: this works only because we have POT. we'd have to round the // texture size up, otherwise. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); free((void*)pixels); } const State& s = drawingState(); if (UNLIKELY(s.alpha < 0xFF)) { const GGLfixed alpha = (s.alpha << 16)/255; glColor4x(0, 0, 0, alpha); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } else { glDisable(GL_BLEND); } glDisable(GL_DITHER); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); if (UNLIKELY(transformed() || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { // This is a very rare scenario. glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(1.0f/w, -1.0f/h, 1); glTranslatef(-x, -y, 0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FIXED, 0, mVertices); glTexCoordPointer(2, GL_FIXED, 0, mVertices); Rect r; while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } else { Region::iterator iterator(clip); if (iterator) { // NOTE: this is marginally faster with the software gl, because // glReadPixels() reads the fb bottom-to-top, however we'll // skip all the jaccobian computations. Rect r; GLint crop[4] = { 0, 0, w, h }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); y = fbHeight - (y + h); while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawTexiOES(x, y, 0, w, h); } } } } glDisableClientState(GL_TEXTURE_COORD_ARRAY); }
void Font::drawString(int x, int y, int fontWidth, int fontHeight, const char *str, DrawAnchor anchor) { #ifndef GL_OES_draw_texture #ifdef DEBUG printf("Unsupport GL_OES_draw_texture extension...\n"); #endif #else glPushMatrix(); glDisable(GL_DEPTH_TEST); glDisable(GL_FOG); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_texture->textureId); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f(m_color->red, m_color->green, m_color->blue, m_color->alpha); GLuint len = strlen(str); for (GLuint i = 0; i < len; i++) { int index = (int)(str[i] - 32); #if (defined(DEBUG) && defined(SHOW_FONT_POS)) printf("str[%d]: %c, index: %d\n", i, str[i], index); #endif GLint crop[4] = { 0, 0, m_charWidth, m_charHeight }; int x_idx = index % m_colCount; int y_idx = (int)(index / m_colCount); crop[0] = x_idx * m_charWidth; crop[1] = (m_rowCount - y_idx) * m_charHeight; #if (defined(DEBUG) && defined(SHOW_FONT_POS)) printf("x_idx: %d, y_idx: %d, crop[0]: %d, crop[1]: %d\n", x_idx, y_idx, crop[0], crop[1]); #endif glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); //calc the x, y & draw int scr_width = World::getInstance()->getWidth(); int scr_height = World::getInstance()->getHeight(); switch (anchor) { case(TOP_LEFT): //if draw from top & left, set y with screen height - image draw height glDrawTexiOES(x + i * fontWidth, scr_height - fontHeight - y, 0, fontWidth, fontHeight); break; case(TOP_RIGHT): glDrawTexiOES(scr_width - (len - i) * fontWidth - x, scr_height - fontHeight - y, 0, fontWidth, fontHeight); break; case(BOTTOM_RIGHT): glDrawTexiOES(scr_width - (len - i) * fontWidth - x, y, 0, fontWidth, fontHeight); break; case(BOTTOM_LEFT): default: glDrawTexiOES(x + i * fontWidth, y, 0, fontWidth, fontHeight); break; } // glDrawTexiOES(x + i * fontWidth, y, 0, fontWidth, fontHeight); } glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPopMatrix(); #endif }
void LayerBase::drawWithOpenGL(const Region& clip, GLint textureName, const GGLSurface& t) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); const State& s(drawingState()); // bind our texture validateTexture(textureName); glEnable(GL_TEXTURE_2D); // Dithering... if (s.flags & ISurfaceComposer::eLayerDither) { glEnable(GL_DITHER); } else { glDisable(GL_DITHER); } if (UNLIKELY(s.alpha < 0xFF)) { // We have an alpha-modulation. We need to modulate all // texture components by alpha because we're always using // premultiplied alpha. // If the texture doesn't have an alpha channel we can // use REPLACE and switch to non premultiplied alpha // blending (SRCA/ONE_MINUS_SRCA). GLenum env, src; if (needsBlending()) { env = GL_MODULATE; src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; } else { env = GL_REPLACE; src = GL_SRC_ALPHA; } const GGLfixed alpha = (s.alpha << 16)/255; glColor4x(alpha, alpha, alpha, alpha); glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); } else { glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glColor4x(0x10000, 0x10000, 0x10000, 0x10000); if (needsBlending()) { GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); } else { glDisable(GL_BLEND); } } if (UNLIKELY(transformed() || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { //StopWatch watch("GL transformed"); Region::iterator iterator(clip); if (iterator) { // always use high-quality filtering with fast configurations bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG); if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } const GLfixed texCoords[4][2] = { { 0, 0 }, { 0, 0x10000 }, { 0x10000, 0x10000 }, { 0x10000, 0 } }; glMatrixMode(GL_TEXTURE); glLoadIdentity(); if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { // find the smallest power-of-two that will accommodate our surface GLuint tw = 1 << (31 - clz(t.width)); GLuint th = 1 << (31 - clz(t.height)); if (tw < t.width) tw <<= 1; if (th < t.height) th <<= 1; // this divide should be relatively fast because it's // a power-of-two (optimized path in libgcc) GLfloat ws = GLfloat(t.width) /tw; GLfloat hs = GLfloat(t.height)/th; glScalef(ws, hs, 1.0f); } glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FIXED, 0, mVertices); glTexCoordPointer(2, GL_FIXED, 0, texCoords); Rect r; while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } else { Region::iterator iterator(clip); if (iterator) { Rect r; GLint crop[4] = { 0, t.height, t.width, -t.height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); int x = tx(); int y = ty(); y = fbHeight - (y + t.height); while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawTexiOES(x, y, 0, t.width, t.height); } } } }
void glDrawTexiOESLogged(GLint x, GLint y, GLint z, GLint width, GLint height) { printf("glDrawTexiOES(%i, %i, %i, %i, %i)\n", x, y, z, width, height); glDrawTexiOES(x, y, z, width, height); }
static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect) { GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; int minx, miny, maxx, maxy; GLfloat minu, maxu, minv, maxv; GLES_ActivateRenderer(renderer); glEnable(GL_TEXTURE_2D); glBindTexture(texturedata->type, texturedata->texture); if (texturedata->scaleMode != data->current.scaleMode) { glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, texturedata->scaleMode); glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, texturedata->scaleMode); data->current.scaleMode = texturedata->scaleMode; } if (texture->modMode) { GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a); } else { GLES_SetColor(data, 255, 255, 255, 255); } GLES_SetBlendMode(data, texture->blendMode); GLES_SetTexCoords(data, SDL_TRUE); if (data->GL_OES_draw_texture_supported && data->useDrawTexture) { /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */ GLint cropRect[4]; int w, h; SDL_Window *window = renderer->window; SDL_GetWindowSize(window, &w, &h); cropRect[0] = srcrect->x; cropRect[1] = srcrect->y + srcrect->h; cropRect[2] = srcrect->w; cropRect[3] = -srcrect->h; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); glDrawTexiOES(dstrect->x, h - dstrect->y - dstrect->h, 0, dstrect->w, dstrect->h); } else { minx = dstrect->x; miny = dstrect->y; maxx = dstrect->x + dstrect->w; maxy = dstrect->y + dstrect->h; minu = (GLfloat) srcrect->x / texture->w; minu *= texturedata->texw; maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; maxu *= texturedata->texw; minv = (GLfloat) srcrect->y / texture->h; minv *= texturedata->texh; maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; maxv *= texturedata->texh; GLshort vertices[8]; GLfloat texCoords[8]; vertices[0] = minx; vertices[1] = miny; vertices[2] = maxx; vertices[3] = miny; vertices[4] = minx; vertices[5] = maxy; vertices[6] = maxx; vertices[7] = maxy; texCoords[0] = minu; texCoords[1] = minv; texCoords[2] = maxu; texCoords[3] = minv; texCoords[4] = minu; texCoords[5] = maxv; texCoords[6] = maxu; texCoords[7] = maxv; glVertexPointer(2, GL_SHORT, 0, vertices); glTexCoordPointer(2, GL_FLOAT, 0, texCoords); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } glDisable(GL_TEXTURE_2D); return 0; }
void LayerBlur::onDraw(const Region& clip) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); int x = mTransformedBounds.left; int y = mTransformedBounds.top; int w = mTransformedBounds.width(); int h = mTransformedBounds.height(); GLint X = x; GLint Y = fbHeight - (y + h); if (X < 0) { w += X; X = 0; } if (Y < 0) { h += Y; Y = 0; } if (w<0 || h<0) { // we're outside of the framebuffer return; } if (mTextureName == -1U) { // create the texture name the first time // can't do that in the ctor, because it runs in another thread. glGenTextures(1, &mTextureName); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType); if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) { mReadFormat = GL_RGBA; mReadType = GL_UNSIGNED_BYTE; mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888; } } Region::const_iterator it = clip.begin(); Region::const_iterator const end = clip.end(); if (it != end) { #if defined(GL_OES_EGL_image_external) if (GLExtensions::getInstance().haveTextureExternal()) { glDisable(GL_TEXTURE_EXTERNAL_OES); } #endif glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mTextureName); if (mRefreshCache) { mRefreshCache = false; mAutoRefreshPending = false; int32_t pixelSize = 4; int32_t s = w; if (mReadType == GL_UNSIGNED_SHORT_5_6_5) { // allocate enough memory for 4-bytes (2 pixels) aligned data s = (w + 1) & ~1; pixelSize = 2; } uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize); // This reads the frame-buffer, so a h/w GL would have to // finish() its rendering first. we don't want to do that // too often. Read data is 4-bytes aligned. glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels); // blur that texture. GGLSurface bl; bl.version = sizeof(GGLSurface); bl.width = w; bl.height = h; bl.stride = s; bl.format = mBlurFormat; bl.data = (GGLubyte*)pixels; blurFilter(&bl, 8, 2); if (GLExtensions::getInstance().haveNpot()) { glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0, mReadFormat, mReadType, pixels); mWidthScale = 1.0f / w; mHeightScale =-1.0f / h; mYOffset = 0; } else { GLuint tw = 1 << (31 - clz(w)); GLuint th = 1 << (31 - clz(h)); if (tw < GLuint(w)) tw <<= 1; if (th < GLuint(h)) th <<= 1; glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0, mReadFormat, mReadType, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, mReadFormat, mReadType, pixels); mWidthScale = 1.0f / tw; mHeightScale =-1.0f / th; mYOffset = th-h; } free((void*)pixels); } const State& s = drawingState(); if (UNLIKELY(s.alpha < 0xFF)) { const GLfloat alpha = s.alpha * (1.0f/255.0f); glColor4f(0, 0, 0, alpha); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } else { glDisable(GL_BLEND); } if (mFlags & DisplayHardware::SLOW_CONFIG) { glDisable(GL_DITHER); } else { glEnable(GL_DITHER); } glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); #ifdef AVOID_DRAW_TEXTURE if(UNLIKELY(transformed())) #endif { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(mWidthScale, mHeightScale, 1); glTranslatef(-x, mYOffset - y, 0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FLOAT, 0, mVertices); glTexCoordPointer(2, GL_FLOAT, 0, mVertices); while (it != end) { const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } glDisableClientState(GL_TEXTURE_COORD_ARRAY); } #ifdef AVOID_DRAW_TEXTURE else{ Rect r; GLint crop[4] = { 0, 0, w, h }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); y = fbHeight - (y + h); while (it != end) { const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawTexiOES(x, y, 0, w, h); } } #endif glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } }
bool BootAnimation::movie() { ZipEntryRO desc = mZip->findEntryByName("desc.txt"); ALOGE_IF(!desc, "couldn't find desc.txt"); if (!desc) { return false; } FileMap* descMap = mZip->createEntryFileMap(desc); mZip->releaseEntry(desc); ALOGE_IF(!descMap, "descMap is null"); if (!descMap) { return false; } String8 desString((char const*)descMap->getDataPtr(), descMap->getDataLength()); descMap->release(); char const* s = desString.string(); Animation animation; // Parse the description file for (;;) { const char* endl = strstr(s, "\n"); if (!endl) break; String8 line(s, endl - s); const char* l = line.string(); int fps, width, height, count, pause; char path[ANIM_ENTRY_NAME_MAX]; char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); animation.width = width; animation.height = height; animation.fps = fps; } else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) { //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path); Animation::Part part; part.playUntilComplete = pathType == 'c'; part.count = count; part.pause = pause; part.path = path; animation.parts.add(part); } s = ++endl; } // read all the data structures const size_t pcount = animation.parts.size(); void *cookie = NULL; if (!mZip->startIteration(&cookie)) { return false; } ZipEntryRO entry; char name[ANIM_ENTRY_NAME_MAX]; while ((entry = mZip->nextEntry(cookie)) != NULL) { const int foundEntryName = mZip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX); if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) { ALOGE("Error fetching entry file name"); continue; } const String8 entryName(name); const String8 path(entryName.getPathDir()); const String8 leaf(entryName.getPathLeaf()); if (leaf.size() > 0) { for (size_t j=0 ; j<pcount ; j++) { if (path == animation.parts[j].path) { int method; // supports only stored png files if (mZip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) { if (method == ZipFileRO::kCompressStored) { FileMap* map = mZip->createEntryFileMap(entry); if (map) { Animation::Frame frame; frame.name = leaf; frame.map = map; Animation::Part& part(animation.parts.editItemAt(j)); part.frames.add(frame); } } } } } } } mZip->endIteration(cookie); // clear screen glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); const int xc = (mWidth - animation.width) / 2; const int yc = ((mHeight - animation.height) / 2); nsecs_t lastFrame = systemTime(); nsecs_t frameDuration = s2ns(1) / animation.fps; Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); for (size_t i=0 ; i<pcount ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); glBindTexture(GL_TEXTURE_2D, 0); for (int r=0 ; !part.count || r<part.count ; r++) { // Exit any non playuntil complete parts immediately if(exitPending() && !part.playUntilComplete) break; for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); if (r > 0) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { if (part.count != 1) { glGenTextures(1, &frame.tid); glBindTexture(GL_TEXTURE_2D, frame.tid); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } initTexture(frame); } if (!clearReg.isEmpty()) { Region::const_iterator head(clearReg.begin()); Region::const_iterator tail(clearReg.end()); glEnable(GL_SCISSOR_TEST); while (head != tail) { const Rect& r(*head++); glScissor(r.left, mHeight - r.bottom, r.width(), r.height()); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } glDrawTexiOES(xc, yc, 0, animation.width, animation.height); eglSwapBuffers(mDisplay, mSurface); nsecs_t now = systemTime(); nsecs_t delay = frameDuration - (now - lastFrame); //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay)); lastFrame = now; if (delay > 0) { struct timespec spec; spec.tv_sec = (now + delay) / 1000000000; spec.tv_nsec = (now + delay) % 1000000000; int err; do { err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); } while (err<0 && errno == EINTR); } checkExit(); } usleep(part.pause * ns2us(frameDuration)); // For infinite parts, we've now played them at least once, so perhaps exit if(exitPending() && !part.count) break; } // free the textures for this part if (part.count != 1) { for (size_t j=0 ; j<fcount ; j++) { const Animation::Frame& frame(part.frames[j]); glDeleteTextures(1, &frame.tid); } } } return false; }
bool BootAnimation::movie() { char bootenabled[PROPERTY_VALUE_MAX]; char bootsound[PROPERTY_VALUE_MAX]; char bootvolume[PROPERTY_VALUE_MAX]; property_get("persist.sys.boot_enabled", bootenabled, "1"); property_get("persist.sys.boot_sound", bootsound, "1"); property_get("persist.sys.boot_volume", bootvolume, "0.2"); bool bootEnabled = atoi(bootenabled) != 0; bool enableSound = atoi(bootsound) != 0; float bootVolume = strtof(bootvolume, NULL); if(!bootEnabled) { return false; } if(enableSound){ sp<MediaPlayer> mediaplay = new MediaPlayer(); mediaplay->setDataSource ("/system/media/audio.mp3", NULL); mediaplay->setVolume (bootVolume, bootVolume); mediaplay->prepare(); mediaplay->start(); } ZipFileRO& zip(mZip); size_t numEntries = zip.getNumEntries(); ZipEntryRO desc = zip.findEntryByName("desc.txt"); FileMap* descMap = zip.createEntryFileMap(desc); ALOGE_IF(!descMap, "descMap is null"); if (!descMap) { return false; } String8 desString((char const*)descMap->getDataPtr(), descMap->getDataLength()); char const* s = desString.string(); Animation animation; float r = 0.0f; float g = 0.0f; float b = 0.0f; // Parse the description file for (;;) { const char* endl = strstr(s, "\n"); if (!endl) break; String8 line(s, endl - s); const char* l = line.string(); int fps, width, height, count, pause, red, green, blue; char path[256]; char pathType; if (sscanf(l, "%d %d %d %d %d %d", &width, &height, &fps, &red, &green, &blue) == 6) { //ALOGD("> w=%d, h=%d, fps=%d, rgb=(%d, %d, %d)", width, height, fps, red, green, blue); animation.width = width; animation.height = height; animation.fps = fps; r = (float) red / 255.0f; g = (float) green / 255.0f; b = (float) blue / 255.0f; } else if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); animation.width = width; animation.height = height; animation.fps = fps; } else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) { //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path); Animation::Part part; part.playUntilComplete = pathType == 'c'; part.count = count; part.pause = pause; part.path = path; animation.parts.add(part); } s = ++endl; } // read all the data structures const size_t pcount = animation.parts.size(); for (size_t i=0 ; i<numEntries ; i++) { char name[256]; ZipEntryRO entry = zip.findEntryByIndex(i); if (zip.getEntryFileName(entry, name, 256) == 0) { const String8 entryName(name); const String8 path(entryName.getPathDir()); const String8 leaf(entryName.getPathLeaf()); if (leaf.size() > 0) { for (size_t j=0 ; j<pcount ; j++) { if (path == animation.parts[j].path) { int method; // supports only stored png files if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) { if (method == ZipFileRO::kCompressStored) { FileMap* map = zip.createEntryFileMap(entry); if (map) { Animation::Frame frame; frame.name = leaf; frame.map = map; Animation::Part& part(animation.parts.editItemAt(j)); part.frames.add(frame); } } } } } } } } #ifndef CONTINUOUS_SPLASH // clear screen glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glClearColor(r,g,b,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); #endif glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); const int xc = (mWidth - animation.width) / 2; const int yc = ((mHeight - animation.height) / 2); nsecs_t lastFrame = systemTime(); nsecs_t frameDuration = s2ns(1) / animation.fps; Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); for (int i=0 ; i<pcount ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); // can be 1, 0, or not set #ifdef NO_TEXTURE_CACHE const int noTextureCache = NO_TEXTURE_CACHE; #else const int noTextureCache = ((animation.width * animation.height * fcount) > 48 * 1024 * 1024) ? 1 : 0; #endif glBindTexture(GL_TEXTURE_2D, 0); for (int r=0 ; !part.count || r<part.count ; r++) { // Exit any non playuntil complete parts immediately if(exitPending() && !part.playUntilComplete) break; for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); if (r > 0 && !noTextureCache) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { if (part.count != 1) { glGenTextures(1, &frame.tid); glBindTexture(GL_TEXTURE_2D, frame.tid); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } initTexture( frame.map->getDataPtr(), frame.map->getDataLength()); } if (!clearReg.isEmpty()) { Region::const_iterator head(clearReg.begin()); Region::const_iterator tail(clearReg.end()); glEnable(GL_SCISSOR_TEST); while (head != tail) { const Rect& r(*head++); glScissor(r.left, mHeight - r.bottom, r.width(), r.height()); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } glDrawTexiOES(xc, yc, 0, animation.width, animation.height); eglSwapBuffers(mDisplay, mSurface); nsecs_t now = systemTime(); nsecs_t delay = frameDuration - (now - lastFrame); //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay)); lastFrame = now; if (delay > 0) { struct timespec spec; spec.tv_sec = (now + delay) / 1000000000; spec.tv_nsec = (now + delay) % 1000000000; int err; do { err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); } while (err<0 && errno == EINTR); } checkExit(); if (noTextureCache) glDeleteTextures(1, &frame.tid); } usleep(part.pause * ns2us(frameDuration)); // For infinite parts, we've now played them at least once, so perhaps exit if(exitPending() && !part.count) break; } // free the textures for this part if (part.count != 1 && !noTextureCache) { for (size_t j=0 ; j<fcount ; j++) { const Animation::Frame& frame(part.frames[j]); glDeleteTextures(1, &frame.tid); } } } return false; }