blob: f1071cf9097b41e5d076e644da2d4e04c42e6888 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2**
3** Copyright 2007 The Android Open Source Project
4**
5** Licensed under the Apache License Version 2.0(the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing software
12** distributed under the License is distributed on an "AS IS" BASIS
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "EGLNativeWindowSurface"
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23
24#include <cutils/log.h>
25#include <cutils/atomic.h>
26
27#include <ui/SurfaceComposerClient.h>
28#include <ui/DisplayInfo.h>
29#include <ui/Rect.h>
30
31#include <EGL/egl.h>
32
33#include <pixelflinger/format.h>
34
35#include <ui/EGLNativeWindowSurface.h>
36
37// ----------------------------------------------------------------------------
38namespace android {
39// ----------------------------------------------------------------------------
40
41EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface)
42 : EGLNativeSurface<EGLNativeWindowSurface>(),
43 mSurface(surface), mConnected(false)
44{
45 egl_native_window_t::magic = 0x600913;
46 egl_native_window_t::version = sizeof(egl_native_window_t);
47 egl_native_window_t::ident = 0;
48 egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef;
49 egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef;
50 egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers;
51 egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect;
52 egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect;
53
54 DisplayInfo dinfo;
55 SurfaceComposerClient::getDisplayInfo(0, &dinfo);
56 egl_native_window_t::xdpi = dinfo.xdpi;
57 egl_native_window_t::ydpi = dinfo.ydpi;
58 egl_native_window_t::fps = dinfo.fps;
59 egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER;
60}
61
62EGLNativeWindowSurface::~EGLNativeWindowSurface()
63{
64 disconnect();
65 mSurface.clear();
66 magic = 0;
67}
68
69void EGLNativeWindowSurface::hook_incRef(NativeWindowType window)
70{
71 EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
72 that->incStrong(that);
73}
74
75void EGLNativeWindowSurface::hook_decRef(NativeWindowType window)
76{
77 EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
78 that->decStrong(that);
79}
80
81void EGLNativeWindowSurface::hook_connect(NativeWindowType window)
82{
83 EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
84 that->connect();
85}
86
87void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window)
88{
89 EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
90 that->disconnect();
91}
92
93uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window)
94{
95 EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
96 return that->swapBuffers();
97}
98
99void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h)
100{
101 mSurface->setSwapRectangle(Rect(l, t, l+w, t+h));
102}
103
104uint32_t EGLNativeWindowSurface::swapBuffers()
105{
106 const int w = egl_native_window_t::width;
107 const int h = egl_native_window_t::height;
108 const sp<Surface>& surface(mSurface);
109 Surface::SurfaceInfo info;
110 surface->unlockAndPost();
111 surface->lock(&info);
112 // update the address of the buffer to draw to next
113 egl_native_window_t::base = intptr_t(info.base);
114 egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
115
116 // update size if it changed
117 if (w != int(info.w) || h != int(info.h)) {
118 egl_native_window_t::width = info.w;
119 egl_native_window_t::height = info.h;
120 egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
121 egl_native_window_t::format = info.format;
122 return EGL_NATIVES_FLAG_SIZE_CHANGED;
123 }
124 return 0;
125}
126
127void EGLNativeWindowSurface::connect()
128{
129 if (!mConnected) {
130 Surface::SurfaceInfo info;
131 mSurface->lock(&info);
132 mSurface->setSwapRectangle(Rect(info.w, info.h));
133 mConnected = true;
134
135 egl_native_window_t::width = info.w;
136 egl_native_window_t::height = info.h;
137 egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
138 egl_native_window_t::format = info.format;
139 egl_native_window_t::base = intptr_t(info.base);
140 egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
141 // FIXME: egl_native_window_t::memory_type used to be set from
142 // mSurface, but we wanted to break this dependency. We set it to
143 // GPU because the software rendered doesn't care, but the h/w
144 // accelerator needs it. Eventually, this value should go away
145 // completely, since memory will be managed by OpenGL.
146 egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU;
147 egl_native_window_t::fd = 0;
148 }
149}
150
151void EGLNativeWindowSurface::disconnect()
152{
153 if (mConnected) {
154 mSurface->unlock();
155 mConnected = false;
156 }
157}
158
159// ----------------------------------------------------------------------------
160}; // namespace android
161// ----------------------------------------------------------------------------