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