LayerBase.cpp revision 78fd5010a87425d2be401d10a306dd68638fc1dd
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#include <stdlib.h>
18#include <stdint.h>
19#include <sys/types.h>
20
21#include <utils/Errors.h>
22#include <utils/Log.h>
23#include <binder/IPCThreadState.h>
24#include <binder/IServiceManager.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 "SurfaceFlinger.h"
34#include "DisplayHardware/DisplayHardware.h"
35
36
37namespace android {
38
39// ---------------------------------------------------------------------------
40
41const uint32_t LayerBase::typeInfo = 1;
42const char* const LayerBase::typeID = "LayerBase";
43
44const uint32_t LayerBaseClient::typeInfo = LayerBase::typeInfo | 2;
45const char* const LayerBaseClient::typeID = "LayerBaseClient";
46
47// ---------------------------------------------------------------------------
48
49LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
50    : dpy(display), contentDirty(false),
51      mFlinger(flinger),
52      mTransformed(false),
53      mUseLinearFiltering(false),
54      mOrientation(0),
55      mLeft(0), mTop(0),
56      mTransactionFlags(0),
57      mPremultipliedAlpha(true), mDebug(false),
58      mInvalidate(0)
59{
60    const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
61    mFlags = hw.getFlags();
62}
63
64LayerBase::~LayerBase()
65{
66}
67
68void LayerBase::setName(const String8& name) {
69    mName = name;
70}
71
72String8 LayerBase::getName() const {
73    return mName;
74}
75
76const GraphicPlane& LayerBase::graphicPlane(int dpy) const
77{
78    return mFlinger->graphicPlane(dpy);
79}
80
81GraphicPlane& LayerBase::graphicPlane(int dpy)
82{
83    return mFlinger->graphicPlane(dpy);
84}
85
86void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
87{
88    uint32_t layerFlags = 0;
89    if (flags & ISurfaceComposer::eHidden)
90        layerFlags = ISurfaceComposer::eLayerHidden;
91
92    if (flags & ISurfaceComposer::eNonPremultiplied)
93        mPremultipliedAlpha = false;
94
95    mCurrentState.z             = 0;
96    mCurrentState.w             = w;
97    mCurrentState.h             = h;
98    mCurrentState.requested_w   = w;
99    mCurrentState.requested_h   = h;
100    mCurrentState.alpha         = 0xFF;
101    mCurrentState.flags         = layerFlags;
102    mCurrentState.sequence      = 0;
103    mCurrentState.transform.set(0, 0);
104
105    // drawing state & current state are identical
106    mDrawingState = mCurrentState;
107}
108
109void LayerBase::commitTransaction() {
110    mDrawingState = mCurrentState;
111}
112void LayerBase::forceVisibilityTransaction() {
113    // this can be called without SurfaceFlinger.mStateLock, but if we
114    // can atomically increment the sequence number, it doesn't matter.
115    android_atomic_inc(&mCurrentState.sequence);
116    requestTransaction();
117}
118bool LayerBase::requestTransaction() {
119    int32_t old = setTransactionFlags(eTransactionNeeded);
120    return ((old & eTransactionNeeded) == 0);
121}
122uint32_t LayerBase::getTransactionFlags(uint32_t flags) {
123    return android_atomic_and(~flags, &mTransactionFlags) & flags;
124}
125uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
126    return android_atomic_or(flags, &mTransactionFlags);
127}
128
129bool LayerBase::setPosition(int32_t x, int32_t y) {
130    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
131        return false;
132    mCurrentState.sequence++;
133    mCurrentState.transform.set(x, y);
134    requestTransaction();
135    return true;
136}
137bool LayerBase::setLayer(uint32_t z) {
138    if (mCurrentState.z == z)
139        return false;
140    mCurrentState.sequence++;
141    mCurrentState.z = z;
142    requestTransaction();
143    return true;
144}
145bool LayerBase::setSize(uint32_t w, uint32_t h) {
146    if (mCurrentState.requested_w == w && mCurrentState.requested_h == h)
147        return false;
148    mCurrentState.requested_w = w;
149    mCurrentState.requested_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 ((front.requested_w != temp.requested_w) ||
207        (front.requested_h != temp.requested_h))  {
208        // resize the layer, set the physical size to the requested size
209        Layer::State& editTemp(currentState());
210        editTemp.w = temp.requested_w;
211        editTemp.h = temp.requested_h;
212    }
213
214    if ((front.w != temp.w) || (front.h != temp.h)) {
215        // invalidate and recompute the visible regions if needed
216        flags |= Layer::eVisibleRegion;
217    }
218
219    if (temp.sequence != front.sequence) {
220        // invalidate and recompute the visible regions if needed
221        flags |= eVisibleRegion;
222        this->contentDirty = true;
223
224        const bool linearFiltering = mUseLinearFiltering;
225        mUseLinearFiltering = false;
226        if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
227            // we may use linear filtering, if the matrix scales us
228            const uint8_t type = temp.transform.getType();
229            if (!temp.transform.preserveRects() || (type >= Transform::SCALE)) {
230                mUseLinearFiltering = true;
231            }
232        }
233    }
234
235    // Commit the transaction
236    commitTransaction();
237    return flags;
238}
239
240void LayerBase::validateVisibility(const Transform& planeTransform)
241{
242    const Layer::State& s(drawingState());
243    const Transform tr(planeTransform * s.transform);
244    const bool transformed = tr.transformed();
245
246    uint32_t w = s.w;
247    uint32_t h = s.h;
248    tr.transform(mVertices[0], 0, 0);
249    tr.transform(mVertices[1], 0, h);
250    tr.transform(mVertices[2], w, h);
251    tr.transform(mVertices[3], w, 0);
252    if (UNLIKELY(transformed)) {
253        // NOTE: here we could also punt if we have too many rectangles
254        // in the transparent region
255        if (tr.preserveRects()) {
256            // transform the transparent region
257            transparentRegionScreen = tr.transform(s.transparentRegion);
258        } else {
259            // transformation too complex, can't do the transparent region
260            // optimization.
261            transparentRegionScreen.clear();
262        }
263    } else {
264        transparentRegionScreen = s.transparentRegion;
265    }
266
267    // cache a few things...
268    mOrientation = tr.getOrientation();
269    mTransformedBounds = tr.makeBounds(w, h);
270    mTransformed = transformed;
271    mLeft = tr.tx();
272    mTop  = tr.ty();
273}
274
275void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
276{
277}
278
279void LayerBase::unlockPageFlip(
280        const Transform& planeTransform, Region& outDirtyRegion)
281{
282    if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
283        outDirtyRegion.orSelf(visibleRegionScreen);
284    }
285}
286
287void LayerBase::finishPageFlip()
288{
289}
290
291void LayerBase::invalidate()
292{
293    if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
294        mFlinger->signalEvent();
295    }
296}
297
298void LayerBase::drawRegion(const Region& reg) const
299{
300    Region::const_iterator it = reg.begin();
301    Region::const_iterator const end = reg.end();
302    if (it != end) {
303        Rect r;
304        const DisplayHardware& hw(graphicPlane(0).displayHardware());
305        const int32_t fbWidth  = hw.getWidth();
306        const int32_t fbHeight = hw.getHeight();
307        const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 },
308                { fbWidth, fbHeight }, { 0, fbHeight }  };
309        glVertexPointer(2, GL_SHORT, 0, vertices);
310        while (it != end) {
311            const Rect& r = *it++;
312            const GLint sy = fbHeight - (r.top + r.height());
313            glScissor(r.left, sy, r.width(), r.height());
314            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
315        }
316    }
317}
318
319void LayerBase::draw(const Region& inClip) const
320{
321    // invalidate the region we'll update
322    Region clip(inClip);  // copy-on-write, so no-op most of the time
323
324    // Remove the transparent area from the clipping region
325    const State& s = drawingState();
326    if (LIKELY(!s.transparentRegion.isEmpty())) {
327        clip.subtract(transparentRegionScreen);
328        if (clip.isEmpty()) {
329            // usually this won't happen because this should be taken care of
330            // by SurfaceFlinger::computeVisibleRegions()
331            return;
332        }
333    }
334
335    // reset GL state
336    glEnable(GL_SCISSOR_TEST);
337
338    onDraw(clip);
339
340    /*
341    glDisable(GL_TEXTURE_2D);
342    glDisable(GL_DITHER);
343    glEnable(GL_BLEND);
344    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
345    glColor4x(0, 0x8000, 0, 0x10000);
346    drawRegion(transparentRegionScreen);
347    glDisable(GL_BLEND);
348    */
349}
350
351GLuint LayerBase::createTexture() const
352{
353    GLuint textureName = -1;
354    glGenTextures(1, &textureName);
355    glBindTexture(GL_TEXTURE_2D, textureName);
356    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
357    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
358    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
359    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
360    return textureName;
361}
362
363void LayerBase::clearWithOpenGL(const Region& clip, GLclampx red,
364                                GLclampx green, GLclampx blue,
365                                GLclampx alpha) const
366{
367    const DisplayHardware& hw(graphicPlane(0).displayHardware());
368    const uint32_t fbHeight = hw.getHeight();
369    glColor4x(red,green,blue,alpha);
370    glDisable(GL_TEXTURE_2D);
371    glDisable(GL_BLEND);
372    glDisable(GL_DITHER);
373
374    Region::const_iterator it = clip.begin();
375    Region::const_iterator const end = clip.end();
376    glEnable(GL_SCISSOR_TEST);
377    glVertexPointer(2, GL_FLOAT, 0, mVertices);
378    while (it != end) {
379        const Rect& r = *it++;
380        const GLint sy = fbHeight - (r.top + r.height());
381        glScissor(r.left, sy, r.width(), r.height());
382        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
383    }
384}
385
386void LayerBase::clearWithOpenGL(const Region& clip) const
387{
388    clearWithOpenGL(clip,0,0,0,0);
389}
390
391void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
392{
393    const DisplayHardware& hw(graphicPlane(0).displayHardware());
394    const uint32_t fbHeight = hw.getHeight();
395    const State& s(drawingState());
396
397    // bind our texture
398    validateTexture(texture.name);
399    uint32_t width  = texture.width;
400    uint32_t height = texture.height;
401
402    glEnable(GL_TEXTURE_2D);
403
404    if (UNLIKELY(s.alpha < 0xFF)) {
405        // We have an alpha-modulation. We need to modulate all
406        // texture components by alpha because we're always using
407        // premultiplied alpha.
408
409        // If the texture doesn't have an alpha channel we can
410        // use REPLACE and switch to non premultiplied alpha
411        // blending (SRCA/ONE_MINUS_SRCA).
412
413        GLenum env, src;
414        if (needsBlending()) {
415            env = GL_MODULATE;
416            src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
417        } else {
418            env = GL_REPLACE;
419            src = GL_SRC_ALPHA;
420        }
421        const GLfloat alpha = s.alpha * (1.0f/255.0f);
422        glColor4f(alpha, alpha, alpha, alpha);
423        glEnable(GL_BLEND);
424        glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
425        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
426    } else {
427        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
428        glColor4f(1, 1, 1, 1);
429        if (needsBlending()) {
430            GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
431            glEnable(GL_BLEND);
432            glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
433        } else {
434            glDisable(GL_BLEND);
435        }
436    }
437
438    Region::const_iterator it = clip.begin();
439    Region::const_iterator const end = clip.end();
440    const GLfloat texCoords[4][2] = {
441            { 0,  0 },
442            { 0,  1 },
443            { 1,  1 },
444            { 1,  0 }
445    };
446
447    glMatrixMode(GL_TEXTURE);
448    glLoadIdentity();
449
450    // the texture's source is rotated
451    switch (texture.transform) {
452        case HAL_TRANSFORM_ROT_90:
453            glTranslatef(0, 1, 0);
454            glRotatef(-90, 0, 0, 1);
455            break;
456        case HAL_TRANSFORM_ROT_180:
457            glTranslatef(1, 1, 0);
458            glRotatef(-180, 0, 0, 1);
459            break;
460        case HAL_TRANSFORM_ROT_270:
461            glTranslatef(1, 0, 0);
462            glRotatef(-270, 0, 0, 1);
463            break;
464    }
465
466    if (texture.NPOTAdjust) {
467        glScalef(texture.wScale, texture.hScale, 1.0f);
468    }
469
470    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
471    glVertexPointer(2, GL_FLOAT, 0, mVertices);
472    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
473
474    while (it != end) {
475        const Rect& r = *it++;
476        const GLint sy = fbHeight - (r.top + r.height());
477        glScissor(r.left, sy, r.width(), r.height());
478        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
479    }
480    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
481}
482
483void LayerBase::validateTexture(GLint textureName) const
484{
485    glBindTexture(GL_TEXTURE_2D, textureName);
486    // TODO: reload the texture if needed
487    // this is currently done in loadTexture() below
488    if (mUseLinearFiltering) {
489        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
490        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
491    } else {
492        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
493        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
494    }
495
496    if (needsDithering()) {
497        glEnable(GL_DITHER);
498    } else {
499        glDisable(GL_DITHER);
500    }
501}
502
503bool LayerBase::isSupportedYuvFormat(int format) const
504{
505    switch (format) {
506        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
507        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
508        case HAL_PIXEL_FORMAT_YCbCr_422_P:
509        case HAL_PIXEL_FORMAT_YCbCr_420_P:
510        case HAL_PIXEL_FORMAT_YCbCr_422_I:
511        case HAL_PIXEL_FORMAT_YCbCr_420_I:
512        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
513            return true;
514    }
515    return false;
516}
517
518void LayerBase::loadTexture(Texture* texture,
519        const Region& dirty, const GGLSurface& t) const
520{
521    if (texture->name == -1U) {
522        // uh?
523        return;
524    }
525
526    glBindTexture(GL_TEXTURE_2D, texture->name);
527
528    /*
529     * In OpenGL ES we can't specify a stride with glTexImage2D (however,
530     * GL_UNPACK_ALIGNMENT is a limited form of stride).
531     * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we
532     * need to do something reasonable (here creating a bigger texture).
533     *
534     * extra pixels = (((stride - width) * pixelsize) / GL_UNPACK_ALIGNMENT);
535     *
536     * This situation doesn't happen often, but some h/w have a limitation
537     * for their framebuffer (eg: must be multiple of 8 pixels), and
538     * we need to take that into account when using these buffers as
539     * textures.
540     *
541     * This should never be a problem with POT textures
542     */
543
544    int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format));
545    unpack = 1 << ((unpack > 3) ? 3 : unpack);
546    glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
547
548    /*
549     * round to POT if needed
550     */
551    if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
552        texture->NPOTAdjust = true;
553    }
554
555    if (texture->NPOTAdjust) {
556        // find the smallest power-of-two that will accommodate our surface
557        texture->potWidth  = 1 << (31 - clz(t.width));
558        texture->potHeight = 1 << (31 - clz(t.height));
559        if (texture->potWidth  < t.width)  texture->potWidth  <<= 1;
560        if (texture->potHeight < t.height) texture->potHeight <<= 1;
561        texture->wScale = float(t.width)  / texture->potWidth;
562        texture->hScale = float(t.height) / texture->potHeight;
563    } else {
564        texture->potWidth  = t.width;
565        texture->potHeight = t.height;
566    }
567
568    Rect bounds(dirty.bounds());
569    GLvoid* data = 0;
570    if (texture->width != t.width || texture->height != t.height) {
571        texture->width  = t.width;
572        texture->height = t.height;
573
574        // texture size changed, we need to create a new one
575        bounds.set(Rect(t.width, t.height));
576        if (t.width  == texture->potWidth &&
577            t.height == texture->potHeight) {
578            // we can do it one pass
579            data = t.data;
580        }
581
582        if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
583            glTexImage2D(GL_TEXTURE_2D, 0,
584                    GL_RGB, texture->potWidth, texture->potHeight, 0,
585                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
586        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
587            glTexImage2D(GL_TEXTURE_2D, 0,
588                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
589                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data);
590        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
591                   t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
592            glTexImage2D(GL_TEXTURE_2D, 0,
593                    GL_RGBA, texture->potWidth, texture->potHeight, 0,
594                    GL_RGBA, GL_UNSIGNED_BYTE, data);
595        } else if (isSupportedYuvFormat(t.format)) {
596            // just show the Y plane of YUV buffers
597            glTexImage2D(GL_TEXTURE_2D, 0,
598                    GL_LUMINANCE, texture->potWidth, texture->potHeight, 0,
599                    GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
600        } else {
601            // oops, we don't handle this format!
602            LOGE("layer %p, texture=%d, using format %d, which is not "
603                 "supported by the GL", this, texture->name, t.format);
604        }
605    }
606    if (!data) {
607        if (t.format == HAL_PIXEL_FORMAT_RGB_565) {
608            glTexSubImage2D(GL_TEXTURE_2D, 0,
609                    0, bounds.top, t.width, bounds.height(),
610                    GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
611                    t.data + bounds.top*t.stride*2);
612        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_4444) {
613            glTexSubImage2D(GL_TEXTURE_2D, 0,
614                    0, bounds.top, t.width, bounds.height(),
615                    GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
616                    t.data + bounds.top*t.stride*2);
617        } else if (t.format == HAL_PIXEL_FORMAT_RGBA_8888 ||
618                   t.format == HAL_PIXEL_FORMAT_RGBX_8888) {
619            glTexSubImage2D(GL_TEXTURE_2D, 0,
620                    0, bounds.top, t.width, bounds.height(),
621                    GL_RGBA, GL_UNSIGNED_BYTE,
622                    t.data + bounds.top*t.stride*4);
623        } else if (isSupportedYuvFormat(t.format)) {
624            // just show the Y plane of YUV buffers
625            glTexSubImage2D(GL_TEXTURE_2D, 0,
626                    0, bounds.top, t.width, bounds.height(),
627                    GL_LUMINANCE, GL_UNSIGNED_BYTE,
628                    t.data + bounds.top*t.stride);
629        }
630    }
631}
632
633status_t LayerBase::initializeEglImage(
634        const sp<GraphicBuffer>& buffer, Texture* texture)
635{
636    status_t err = NO_ERROR;
637
638    // we need to recreate the texture
639    EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
640
641    // free the previous image
642    if (texture->image != EGL_NO_IMAGE_KHR) {
643        eglDestroyImageKHR(dpy, texture->image);
644        texture->image = EGL_NO_IMAGE_KHR;
645    }
646
647    // construct an EGL_NATIVE_BUFFER_ANDROID
648    android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
649
650    // create the new EGLImageKHR
651    const EGLint attrs[] = {
652            EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
653            EGL_NONE,                   EGL_NONE
654    };
655    texture->image = eglCreateImageKHR(
656            dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
657            (EGLClientBuffer)clientBuf, attrs);
658
659    if (texture->image != EGL_NO_IMAGE_KHR) {
660        glBindTexture(GL_TEXTURE_2D, texture->name);
661        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
662                (GLeglImageOES)texture->image);
663        GLint error = glGetError();
664        if (UNLIKELY(error != GL_NO_ERROR)) {
665            LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
666                 "failed err=0x%04x",
667                 this, texture->image, error);
668            err = INVALID_OPERATION;
669        } else {
670            // Everything went okay!
671            texture->NPOTAdjust = false;
672            texture->dirty  = false;
673            texture->width  = clientBuf->width;
674            texture->height = clientBuf->height;
675        }
676    } else {
677        LOGE("layer=%p, eglCreateImageKHR() failed. err=0x%4x",
678                this, eglGetError());
679        err = INVALID_OPERATION;
680    }
681    return err;
682}
683
684
685// ---------------------------------------------------------------------------
686
687int32_t LayerBaseClient::sIdentity = 0;
688
689LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
690        const sp<Client>& client, int32_t i)
691    : LayerBase(flinger, display), lcblk(NULL), client(client), mIndex(i),
692      mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
693{
694    lcblk = new SharedBufferServer(
695            client->ctrlblk, i, NUM_BUFFERS,
696            mIdentity);
697}
698
699void LayerBaseClient::onFirstRef()
700{
701    sp<Client> client(this->client.promote());
702    if (client != 0) {
703        client->bindLayer(this, mIndex);
704    }
705}
706
707LayerBaseClient::~LayerBaseClient()
708{
709    sp<Client> client(this->client.promote());
710    if (client != 0) {
711        client->free(mIndex);
712    }
713    delete lcblk;
714}
715
716int32_t LayerBaseClient::serverIndex() const
717{
718    sp<Client> client(this->client.promote());
719    if (client != 0) {
720        return (client->cid<<16)|mIndex;
721    }
722    return 0xFFFF0000 | mIndex;
723}
724
725sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
726{
727    sp<Surface> s;
728    Mutex::Autolock _l(mLock);
729    s = mClientSurface.promote();
730    if (s == 0) {
731        s = createSurface();
732        mClientSurface = s;
733    }
734    return s;
735}
736
737sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
738{
739    return new Surface(mFlinger, clientIndex(), mIdentity,
740            const_cast<LayerBaseClient *>(this));
741}
742
743// called with SurfaceFlinger::mStateLock as soon as the layer is entered
744// in the purgatory list
745void LayerBaseClient::onRemoved()
746{
747    // wake up the condition
748    lcblk->setStatus(NO_INIT);
749}
750
751// ---------------------------------------------------------------------------
752
753LayerBaseClient::Surface::Surface(
754        const sp<SurfaceFlinger>& flinger,
755        SurfaceID id, int identity,
756        const sp<LayerBaseClient>& owner)
757    : mFlinger(flinger), mToken(id), mIdentity(identity), mOwner(owner)
758{
759}
760
761LayerBaseClient::Surface::~Surface()
762{
763    /*
764     * This is a good place to clean-up all client resources
765     */
766
767    // destroy client resources
768    sp<LayerBaseClient> layer = getOwner();
769    if (layer != 0) {
770        mFlinger->destroySurface(layer);
771    }
772}
773
774sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
775    sp<LayerBaseClient> owner(mOwner.promote());
776    return owner;
777}
778
779status_t LayerBaseClient::Surface::onTransact(
780        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
781{
782    switch (code) {
783        case REGISTER_BUFFERS:
784        case UNREGISTER_BUFFERS:
785        case CREATE_OVERLAY:
786        {
787            if (!mFlinger->mAccessSurfaceFlinger.checkCalling()) {
788                IPCThreadState* ipc = IPCThreadState::self();
789                const int pid = ipc->getCallingPid();
790                const int uid = ipc->getCallingUid();
791                LOGE("Permission Denial: "
792                        "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
793                return PERMISSION_DENIED;
794            }
795        }
796    }
797    return BnSurface::onTransact(code, data, reply, flags);
798}
799
800sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage)
801{
802    return NULL;
803}
804
805status_t LayerBaseClient::Surface::registerBuffers(
806        const ISurface::BufferHeap& buffers)
807{
808    return INVALID_OPERATION;
809}
810
811void LayerBaseClient::Surface::postBuffer(ssize_t offset)
812{
813}
814
815void LayerBaseClient::Surface::unregisterBuffers()
816{
817}
818
819sp<OverlayRef> LayerBaseClient::Surface::createOverlay(
820        uint32_t w, uint32_t h, int32_t format, int32_t orientation)
821{
822    return NULL;
823};
824
825// ---------------------------------------------------------------------------
826
827}; // namespace android
828