1/*
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
741