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