public void draw(GL10 gl, ESCREEN_ROTATION screenRotation) { if (!mInitialized) return; gl.glEnable(GL10.GL_TEXTURE_2D); gl.glBindTexture(GL10.GL_TEXTURE_2D, mTexture); if (mMustUpdateTexture) { if(!mTextureInitialized) { // Allocate camera image texture once with 2^n dimensions gl.glTexImage2D( GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, mTextureWidth, mTextureHeight, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, null); mTextureInitialized = true; } // ...but only overwrite the camera image-sized region gl.glTexSubImage2D( GL10.GL_TEXTURE_2D, 0, 0, 0, mCameraImageWidth, mCameraImageHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, mTextureBuffer); final float xRatio = (float)mCameraImageWidth / mTextureWidth; final float yRatio = (float)mCameraImageHeight / mTextureHeight; final boolean cameraIsRotated = screenRotation == ESCREEN_ROTATION.ESCREEN_ROTATION_90 || screenRotation == ESCREEN_ROTATION.ESCREEN_ROTATION_270; final float cameraAspect = cameraIsRotated ? 1.0f/mCameraAspect : mCameraAspect; Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); DisplayMetrics displayMetrics = new DisplayMetrics(); display.getMetrics(displayMetrics); // DisplayMetrics.widthPixels/heightPixels are the width/height in the current // orientation (i.e. values get swapped when you rotate the device) float screenAspect = (float)displayMetrics.widthPixels / displayMetrics.heightPixels; float offsetX, offsetY; if (cameraAspect > screenAspect) { // Camera image is wider (e.g. 480x640 camera image vs. a 480x800 device, example // in portrait mode), so crop the width of the camera image float aspectRatio = screenAspect / cameraAspect; offsetX = 0.5f * (1 - aspectRatio); offsetY = 0; mScaleX = cameraAspect / screenAspect; mScaleY = 1; } else { // Screen is wider, so crop the height of the camera image float aspectRatio = cameraAspect / screenAspect; offsetY = 0.5f * (1 - aspectRatio); offsetX = 0; mScaleX = 1; mScaleY = screenAspect / cameraAspect; } if (cameraIsRotated) { // Camera image will be rendered with +-90� rotation, so switch UV coordinates float tmp = offsetX; offsetX = offsetY; offsetY = tmp; } // Calculate texture coordinates. offsetX/offsetY are for cropping if camera and screen // aspect ratios differ. xRatio/yRatio are here because the OpenGL texture has // dimensions of 2^n, but the camera image does not fill it completely (e.g. camera // image 640x480 vs. texture size 1024x512). mTexCoordsBuffer.put(new float[] { offsetX * xRatio, (1-offsetY) * yRatio, (1-offsetX) * xRatio, (1-offsetY) * yRatio, offsetX * xRatio, offsetY * yRatio, (1-offsetX) * xRatio, offsetY * yRatio }); mTexCoordsBuffer.rewind(); mMustUpdateTexture = false; } gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexCoordsBuffer); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glPushMatrix(); gl.glLoadIdentity(); switch (screenRotation) { // Portrait case ESCREEN_ROTATION_270: gl.glRotatef(-90, 0, 0, 1); break; // Reverse portrait (upside down) case ESCREEN_ROTATION_90: gl.glRotatef(90, 0, 0, 1); break; // Landscape (right side of tall device facing up) case ESCREEN_ROTATION_0: break; // Reverse landscape (left side of tall device facing up) case ESCREEN_ROTATION_180: gl.glRotatef(180, 0, 0, 1); break; default: Log.e(TAG, "Unknown screen rotation"); } gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glPopMatrix(); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glPopMatrix(); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE); gl.glDisable(GL10.GL_TEXTURE_2D); }