blob: bdefba34e23377ed86baf95ed2c511d0bcf17136 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2007 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
17#define LOG_TAG "SurfaceFlinger"
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
22
23#include <utils/Errors.h>
24#include <utils/Log.h>
25
26#include "clz.h"
27#include "LayerBase.h"
28#include "LayerBlur.h"
29#include "SurfaceFlinger.h"
30#include "DisplayHardware/DisplayHardware.h"
31
32
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080033// We don't honor the premultiplied alpha flags, which means that
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070034// premultiplied surface may be composed using a non-premultiplied
35// equation. We do this because it may be a lot faster on some hardware
36// The correct value is HONOR_PREMULTIPLIED_ALPHA = 1
37#define HONOR_PREMULTIPLIED_ALPHA 0
38
39namespace android {
40
41// ---------------------------------------------------------------------------
42
43const uint32_t LayerBase::typeInfo = 1;
44const char* const LayerBase::typeID = "LayerBase";
45
46const uint32_t LayerBaseClient::typeInfo = LayerBase::typeInfo | 2;
47const char* const LayerBaseClient::typeID = "LayerBaseClient";
48
49// ---------------------------------------------------------------------------
50
51Vector<GLuint> LayerBase::deletedTextures;
52
53int32_t LayerBase::sIdentity = 0;
54
55LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
The Android Open Source Project27629322009-01-09 17:51:23 -080056 : dpy(display), contentDirty(false),
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070057 mFlinger(flinger),
58 mTransformed(false),
59 mOrientation(0),
60 mCanUseCopyBit(false),
61 mTransactionFlags(0),
62 mPremultipliedAlpha(true),
The Android Open Source Project27629322009-01-09 17:51:23 -080063 mIdentity(uint32_t(android_atomic_inc(&sIdentity))),
64 mInvalidate(0)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070065{
66 const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
67 mFlags = hw.getFlags();
68}
69
70LayerBase::~LayerBase()
71{
72}
73
74const GraphicPlane& LayerBase::graphicPlane(int dpy) const
75{
76 return mFlinger->graphicPlane(dpy);
77}
78
79GraphicPlane& LayerBase::graphicPlane(int dpy)
80{
81 return mFlinger->graphicPlane(dpy);
82}
83
84void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
85{
86 uint32_t layerFlags = 0;
87 if (flags & ISurfaceComposer::eHidden)
88 layerFlags = ISurfaceComposer::eLayerHidden;
89
90 if (flags & ISurfaceComposer::eNonPremultiplied)
91 mPremultipliedAlpha = false;
92
93 mCurrentState.z = 0;
94 mCurrentState.w = w;
95 mCurrentState.h = h;
96 mCurrentState.alpha = 0xFF;
97 mCurrentState.flags = layerFlags;
98 mCurrentState.sequence = 0;
99 mCurrentState.transform.set(0, 0);
100
101 // drawing state & current state are identical
102 mDrawingState = mCurrentState;
103}
104
105void LayerBase::commitTransaction(bool skipSize) {
106 const uint32_t w = mDrawingState.w;
107 const uint32_t h = mDrawingState.h;
108 mDrawingState = mCurrentState;
109 if (skipSize) {
110 mDrawingState.w = w;
111 mDrawingState.h = h;
112 }
113}
114bool LayerBase::requestTransaction() {
115 int32_t old = setTransactionFlags(eTransactionNeeded);
116 return ((old & eTransactionNeeded) == 0);
117}
118uint32_t LayerBase::getTransactionFlags(uint32_t flags) {
119 return android_atomic_and(~flags, &mTransactionFlags) & flags;
120}
121uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
122 return android_atomic_or(flags, &mTransactionFlags);
123}
124
125void LayerBase::setSizeChanged(uint32_t w, uint32_t h) {
126}
127
128bool LayerBase::setPosition(int32_t x, int32_t y) {
129 if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
130 return false;
131 mCurrentState.sequence++;
132 mCurrentState.transform.set(x, y);
133 requestTransaction();
134 return true;
135}
136bool LayerBase::setLayer(uint32_t z) {
137 if (mCurrentState.z == z)
138 return false;
139 mCurrentState.sequence++;
140 mCurrentState.z = z;
141 requestTransaction();
142 return true;
143}
144bool LayerBase::setSize(uint32_t w, uint32_t h) {
145 if (mCurrentState.w == w && mCurrentState.h == h)
146 return false;
147 setSizeChanged(w, h);
148 mCurrentState.w = w;
149 mCurrentState.h = h;
150 requestTransaction();
151 return true;
152}
153bool LayerBase::setAlpha(uint8_t alpha) {
154 if (mCurrentState.alpha == alpha)
155 return false;
156 mCurrentState.sequence++;
157 mCurrentState.alpha = alpha;
158 requestTransaction();
159 return true;
160}
161bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
162 // TODO: check the matrix has changed
163 mCurrentState.sequence++;
164 mCurrentState.transform.set(
165 matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
166 requestTransaction();
167 return true;
168}
169bool LayerBase::setTransparentRegionHint(const Region& transparent) {
170 // TODO: check the region has changed
171 mCurrentState.sequence++;
172 mCurrentState.transparentRegion = transparent;
173 requestTransaction();
174 return true;
175}
176bool LayerBase::setFlags(uint8_t flags, uint8_t mask) {
177 const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
178 if (mCurrentState.flags == newFlags)
179 return false;
180 mCurrentState.sequence++;
181 mCurrentState.flags = newFlags;
182 requestTransaction();
183 return true;
184}
185
186Rect LayerBase::visibleBounds() const
187{
188 return mTransformedBounds;
189}
190
191void LayerBase::setVisibleRegion(const Region& visibleRegion) {
192 // always called from main thread
193 visibleRegionScreen = visibleRegion;
194}
195
196void LayerBase::setCoveredRegion(const Region& coveredRegion) {
197 // always called from main thread
198 coveredRegionScreen = coveredRegion;
199}
200
201uint32_t LayerBase::doTransaction(uint32_t flags)
202{
203 const Layer::State& front(drawingState());
204 const Layer::State& temp(currentState());
205
206 if (temp.sequence != front.sequence) {
207 // invalidate and recompute the visible regions if needed
208 flags |= eVisibleRegion;
The Android Open Source Project27629322009-01-09 17:51:23 -0800209 this->contentDirty = true;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700210 }
211
212 // Commit the transaction
213 commitTransaction(flags & eRestartTransaction);
214 return flags;
215}
216
217Point LayerBase::getPhysicalSize() const
218{
219 const Layer::State& front(drawingState());
220 return Point(front.w, front.h);
221}
222
223void LayerBase::validateVisibility(const Transform& planeTransform)
224{
225 const Layer::State& s(drawingState());
226 const Transform tr(planeTransform * s.transform);
227 const bool transformed = tr.transformed();
228
229 const Point size(getPhysicalSize());
230 uint32_t w = size.x;
231 uint32_t h = size.y;
232 tr.transform(mVertices[0], 0, 0);
233 tr.transform(mVertices[1], 0, h);
234 tr.transform(mVertices[2], w, h);
235 tr.transform(mVertices[3], w, 0);
236 if (UNLIKELY(transformed)) {
237 // NOTE: here we could also punt if we have too many rectangles
238 // in the transparent region
239 if (tr.preserveRects()) {
240 // transform the transparent region
241 transparentRegionScreen = tr.transform(s.transparentRegion);
242 } else {
243 // transformation too complex, can't do the transparent region
244 // optimization.
245 transparentRegionScreen.clear();
246 }
247 } else {
248 transparentRegionScreen = s.transparentRegion;
249 }
250
251 // cache a few things...
252 mOrientation = tr.getOrientation();
253 mTransformedBounds = tr.makeBounds(w, h);
254 mTransformed = transformed;
255 mLeft = tr.tx();
256 mTop = tr.ty();
257
258 // see if we can/should use 2D h/w with the new configuration
259 mCanUseCopyBit = false;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800260 copybit_device_t* copybit = mFlinger->getBlitEngine();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700261 if (copybit) {
262 const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG);
263 const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS);
264 mCanUseCopyBit = true;
265 if ((mOrientation < 0) && (step > 1)) {
266 // arbitrary orientations not supported
267 mCanUseCopyBit = false;
268 } else if ((mOrientation > 0) && (step > 90)) {
269 // 90 deg rotations not supported
270 mCanUseCopyBit = false;
271 } else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) {
272 // arbitrary scaling not supported
273 mCanUseCopyBit = false;
274 }
275#if HONOR_PREMULTIPLIED_ALPHA
276 else if (needsBlending() && mPremultipliedAlpha) {
277 // pre-multiplied alpha not supported
278 mCanUseCopyBit = false;
279 }
280#endif
281 else {
282 // here, we determined we can use copybit
283 if (tr.getType() & SkMatrix::kScale_Mask) {
284 // and we have scaling
285 if (!transparentRegionScreen.isRect()) {
286 // we punt because blending is cheap (h/w) and the region is
287 // complex, which may causes artifacts when copying
288 // scaled content
289 transparentRegionScreen.clear();
290 }
291 }
292 }
293 }
294}
295
296void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
297{
298}
299
300void LayerBase::unlockPageFlip(
301 const Transform& planeTransform, Region& outDirtyRegion)
302{
The Android Open Source Project27629322009-01-09 17:51:23 -0800303 if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
304 outDirtyRegion.orSelf(visibleRegionScreen);
305 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700306}
307
308void LayerBase::finishPageFlip()
309{
310}
311
The Android Open Source Project27629322009-01-09 17:51:23 -0800312void LayerBase::invalidate()
313{
314 if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
315 mFlinger->signalEvent();
316 }
317}
318
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700319void LayerBase::drawRegion(const Region& reg) const
320{
321 Region::iterator iterator(reg);
322 if (iterator) {
323 Rect r;
324 const DisplayHardware& hw(graphicPlane(0).displayHardware());
325 const int32_t fbWidth = hw.getWidth();
326 const int32_t fbHeight = hw.getHeight();
327 const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 },
328 { fbWidth, fbHeight }, { 0, fbHeight } };
329 glVertexPointer(2, GL_SHORT, 0, vertices);
330 while (iterator.iterate(&r)) {
331 const GLint sy = fbHeight - (r.top + r.height());
332 glScissor(r.left, sy, r.width(), r.height());
333 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
334 }
335 }
336}
337
338void LayerBase::draw(const Region& inClip) const
339{
340 // invalidate the region we'll update
341 Region clip(inClip); // copy-on-write, so no-op most of the time
342
343 // Remove the transparent area from the clipping region
344 const State& s = drawingState();
345 if (LIKELY(!s.transparentRegion.isEmpty())) {
346 clip.subtract(transparentRegionScreen);
347 if (clip.isEmpty()) {
348 // usually this won't happen because this should be taken care of
349 // by SurfaceFlinger::computeVisibleRegions()
350 return;
351 }
352 }
353 onDraw(clip);
354
355 /*
356 glDisable(GL_TEXTURE_2D);
357 glDisable(GL_DITHER);
358 glEnable(GL_BLEND);
359 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
360 glColor4x(0, 0x8000, 0, 0x10000);
361 drawRegion(transparentRegionScreen);
362 glDisable(GL_BLEND);
363 */
364}
365
366GLuint LayerBase::createTexture() const
367{
368 GLuint textureName = -1;
369 glGenTextures(1, &textureName);
370 glBindTexture(GL_TEXTURE_2D, textureName);
371 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
372 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
373 if (mFlags & DisplayHardware::SLOW_CONFIG) {
374 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
375 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
376 } else {
377 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
378 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
379 }
380 return textureName;
381}
382
383void LayerBase::clearWithOpenGL(const Region& clip) const
384{
385 const DisplayHardware& hw(graphicPlane(0).displayHardware());
386 const uint32_t fbHeight = hw.getHeight();
387 glColor4x(0,0,0,0);
388 glDisable(GL_TEXTURE_2D);
389 glDisable(GL_BLEND);
390 glDisable(GL_DITHER);
391 Rect r;
392 Region::iterator iterator(clip);
393 if (iterator) {
394 glVertexPointer(2, GL_FIXED, 0, mVertices);
395 while (iterator.iterate(&r)) {
396 const GLint sy = fbHeight - (r.top + r.height());
397 glScissor(r.left, sy, r.width(), r.height());
398 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
399 }
400 }
401}
402
403void LayerBase::drawWithOpenGL(const Region& clip,
404 GLint textureName, const GGLSurface& t) const
405{
406 const DisplayHardware& hw(graphicPlane(0).displayHardware());
407 const uint32_t fbHeight = hw.getHeight();
408 const State& s(drawingState());
409
410 // bind our texture
411 validateTexture(textureName);
412 glEnable(GL_TEXTURE_2D);
413
414 // Dithering...
415 if (s.flags & ISurfaceComposer::eLayerDither) {
416 glEnable(GL_DITHER);
417 } else {
418 glDisable(GL_DITHER);
419 }
420
421 if (UNLIKELY(s.alpha < 0xFF)) {
422 // We have an alpha-modulation. We need to modulate all
423 // texture components by alpha because we're always using
424 // premultiplied alpha.
425
426 // If the texture doesn't have an alpha channel we can
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800427 // use REPLACE and switch to non premultiplied alpha
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700428 // blending (SRCA/ONE_MINUS_SRCA).
429
430 GLenum env, src;
431 if (needsBlending()) {
432 env = GL_MODULATE;
433 src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
434 } else {
435 env = GL_REPLACE;
436 src = GL_SRC_ALPHA;
437 }
438 const GGLfixed alpha = (s.alpha << 16)/255;
439 glColor4x(alpha, alpha, alpha, alpha);
440 glEnable(GL_BLEND);
441 glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
442 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
443 } else {
444 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800445 glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700446 if (needsBlending()) {
447 GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
448 glEnable(GL_BLEND);
449 glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700450 } else {
451 glDisable(GL_BLEND);
452 }
453 }
454
455 if (UNLIKELY(transformed()
456 || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) ))
457 {
458 //StopWatch watch("GL transformed");
459 Region::iterator iterator(clip);
460 if (iterator) {
461 // always use high-quality filtering with fast configurations
462 bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG);
463 if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
464 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
465 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
466 }
467 const GLfixed texCoords[4][2] = {
468 { 0, 0 },
469 { 0, 0x10000 },
470 { 0x10000, 0x10000 },
471 { 0x10000, 0 }
472 };
473
474 glMatrixMode(GL_TEXTURE);
475 glLoadIdentity();
476 if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800477 // find the smallest power-of-two that will accommodate our surface
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700478 GLuint tw = 1 << (31 - clz(t.width));
479 GLuint th = 1 << (31 - clz(t.height));
480 if (tw < t.width) tw <<= 1;
481 if (th < t.height) th <<= 1;
482 // this divide should be relatively fast because it's
483 // a power-of-two (optimized path in libgcc)
484 GLfloat ws = GLfloat(t.width) /tw;
485 GLfloat hs = GLfloat(t.height)/th;
486 glScalef(ws, hs, 1.0f);
487 }
488
489 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
490 glVertexPointer(2, GL_FIXED, 0, mVertices);
491 glTexCoordPointer(2, GL_FIXED, 0, texCoords);
492
493 Rect r;
494 while (iterator.iterate(&r)) {
495 const GLint sy = fbHeight - (r.top + r.height());
496 glScissor(r.left, sy, r.width(), r.height());
497 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
498 }
499
500 if (!fast && s.flags & ISurfaceComposer::eLayerFilter) {
501 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
502 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
503 }
504 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
505 }
506 } else {
507 Region::iterator iterator(clip);
508 if (iterator) {
509 Rect r;
510 GLint crop[4] = { 0, t.height, t.width, -t.height };
511 glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
512 int x = tx();
513 int y = ty();
514 y = fbHeight - (y + t.height);
515 while (iterator.iterate(&r)) {
516 const GLint sy = fbHeight - (r.top + r.height());
517 glScissor(r.left, sy, r.width(), r.height());
518 glDrawTexiOES(x, y, 0, t.width, t.height);
519 }
520 }
521 }
522}
523
524void LayerBase::validateTexture(GLint textureName) const
525{
526 glBindTexture(GL_TEXTURE_2D, textureName);
527 // TODO: reload the texture if needed
528 // this is currently done in loadTexture() below
529}
530
531void LayerBase::loadTexture(const Region& dirty,
532 GLint textureName, const GGLSurface& t,
533 GLuint& textureWidth, GLuint& textureHeight) const
534{
535 // TODO: defer the actual texture reload until LayerBase::validateTexture
536 // is called.
537
538 uint32_t flags = mFlags;
539 glBindTexture(GL_TEXTURE_2D, textureName);
540
541 GLuint tw = t.width;
542 GLuint th = t.height;
543
544 /*
545 * In OpenGL ES we can't specify a stride with glTexImage2D (however,
546 * GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of
547 * stride).
548 * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
549 * need to do something reasonable (here creating a bigger texture).
550 *
551 * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT);
552 *
553 * This situation doesn't happen often, but some h/w have a limitation
554 * for their framebuffer (eg: must be multiple of 8 pixels), and
555 * we need to take that into account when using these buffers as
556 * textures.
557 *
558 * This should never be a problem with POT textures
559 */
560
561 tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4);
562
563 /*
564 * round to POT if needed
565 */
566
567 GLuint texture_w = tw;
568 GLuint texture_h = th;
569 if (!(flags & DisplayHardware::NPOT_EXTENSION)) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800570 // find the smallest power-of-two that will accommodate our surface
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700571 texture_w = 1 << (31 - clz(t.width));
572 texture_h = 1 << (31 - clz(t.height));
573 if (texture_w < t.width) texture_w <<= 1;
574 if (texture_h < t.height) texture_h <<= 1;
575 if (texture_w != tw || texture_h != th) {
576 // we can't use DIRECT_TEXTURE since we changed the size
577 // of the texture
578 flags &= ~DisplayHardware::DIRECT_TEXTURE;
579 }
580 }
581
582 if (flags & DisplayHardware::DIRECT_TEXTURE) {
583 // here we're guaranteed that texture_{w|h} == t{w|h}
584 if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
585 glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
586 GL_RGB, tw, th, 0,
587 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data);
588 } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
589 glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
590 GL_RGBA, tw, th, 0,
591 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data);
592 } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
593 glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0,
594 GL_RGBA, tw, th, 0,
595 GL_RGBA, GL_UNSIGNED_BYTE, t.data);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800596 } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) {
597 // TODO: add GL_BGRA extension
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700598 } else {
599 // oops, we don't handle this format, try the regular path
600 goto regular;
601 }
602 textureWidth = tw;
603 textureHeight = th;
604 } else {
605regular:
606 Rect bounds(dirty.bounds());
607 GLvoid* data = 0;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800608 if (texture_w!=textureWidth || texture_h!=textureHeight) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700609 // texture size changed, we need to create a new one
610
611 if (!textureWidth || !textureHeight) {
612 // this is the first time, load the whole texture
613 if (texture_w==tw && texture_h==th) {
614 // we can do it one pass
615 data = t.data;
616 } else {
617 // we have to create the texture first because it
618 // doesn't match the size of the buffer
619 bounds.set(Rect(tw, th));
620 }
621 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800622
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700623 if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
624 glTexImage2D(GL_TEXTURE_2D, 0,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800625 GL_RGB, texture_w, texture_h, 0,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700626 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
627 } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
628 glTexImage2D(GL_TEXTURE_2D, 0,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800629 GL_RGBA, texture_w, texture_h, 0,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700630 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
631 } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
632 glTexImage2D(GL_TEXTURE_2D, 0,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800633 GL_RGBA, texture_w, texture_h, 0,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700634 GL_RGBA, GL_UNSIGNED_BYTE, data);
635 } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP ||
636 t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
637 // just show the Y plane of YUV buffers
638 data = t.data;
639 glTexImage2D(GL_TEXTURE_2D, 0,
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800640 GL_LUMINANCE, texture_w, texture_h, 0,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700641 GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800642 } else {
643 // oops, we don't handle this format!
644 LOGE("layer %p, texture=%d, using format %d, which is not "
645 "supported by the GL", this, textureName, t.format);
646 textureName = -1;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700647 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800648 textureWidth = texture_w;
649 textureHeight = texture_h;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700650 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800651 if (!data && textureName>=0) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700652 if (t.format == GGL_PIXEL_FORMAT_RGB_565) {
653 glTexSubImage2D(GL_TEXTURE_2D, 0,
654 0, bounds.top, t.width, bounds.height(),
655 GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
656 t.data + bounds.top*t.width*2);
657 } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) {
658 glTexSubImage2D(GL_TEXTURE_2D, 0,
659 0, bounds.top, t.width, bounds.height(),
660 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
661 t.data + bounds.top*t.width*2);
662 } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) {
663 glTexSubImage2D(GL_TEXTURE_2D, 0,
664 0, bounds.top, t.width, bounds.height(),
665 GL_RGBA, GL_UNSIGNED_BYTE,
666 t.data + bounds.top*t.width*4);
667 }
668 }
669 }
670}
671
672bool LayerBase::canUseCopybit() const
673{
674 return mCanUseCopyBit;
675}
676
677// ---------------------------------------------------------------------------
678
679LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
680 Client* c, int32_t i)
681 : LayerBase(flinger, display), client(c),
682 lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ),
683 mIndex(i)
684{
685 if (client) {
686 client->bindLayer(this, i);
687
688 // Initialize this layer's control block
689 memset(this->lcblk, 0, sizeof(layer_cblk_t));
690 this->lcblk->identity = mIdentity;
691 Region::writeEmpty(&(this->lcblk->region[0]), sizeof(flat_region_t));
692 Region::writeEmpty(&(this->lcblk->region[1]), sizeof(flat_region_t));
693 }
694}
695
696LayerBaseClient::~LayerBaseClient()
697{
698 if (client) {
699 client->free(mIndex);
700 }
701}
702
703int32_t LayerBaseClient::serverIndex() const {
704 if (client) {
705 return (client->cid<<16)|mIndex;
706 }
707 return 0xFFFF0000 | mIndex;
708}
709
710sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const
711{
712 return new Surface(clientIndex(), mIdentity);
713}
714
715
716// ---------------------------------------------------------------------------
717
718}; // namespace android