SurfaceTextureClient.cpp revision eafabcdc1639fb96062d9e3c39b0ae27b0238ae1
1/* 2 * Copyright (C) 2010 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 "SurfaceTextureClient" 18//#define LOG_NDEBUG 0 19 20#include <gui/SurfaceTextureClient.h> 21 22#include <utils/Log.h> 23 24namespace android { 25 26SurfaceTextureClient::SurfaceTextureClient( 27 const sp<ISurfaceTexture>& surfaceTexture): 28 mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0), 29 mReqHeight(0), mReqFormat(0), mReqUsage(0), 30 mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0), 31 mQueryWidth(0), mQueryHeight(0), mQueryFormat(0), 32 mMutex() { 33 // Initialize the ANativeWindow function pointers. 34 ANativeWindow::setSwapInterval = setSwapInterval; 35 ANativeWindow::dequeueBuffer = dequeueBuffer; 36 ANativeWindow::cancelBuffer = cancelBuffer; 37 ANativeWindow::lockBuffer = lockBuffer; 38 ANativeWindow::queueBuffer = queueBuffer; 39 ANativeWindow::query = query; 40 ANativeWindow::perform = perform; 41 42 // Get a reference to the allocator. 43 mAllocator = mSurfaceTexture->getAllocator(); 44} 45 46sp<ISurfaceTexture> SurfaceTextureClient::getISurfaceTexture() const { 47 return mSurfaceTexture; 48} 49 50int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) { 51 SurfaceTextureClient* c = getSelf(window); 52 return c->setSwapInterval(interval); 53} 54 55int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window, 56 ANativeWindowBuffer** buffer) { 57 SurfaceTextureClient* c = getSelf(window); 58 return c->dequeueBuffer(buffer); 59} 60 61int SurfaceTextureClient::cancelBuffer(ANativeWindow* window, 62 ANativeWindowBuffer* buffer) { 63 SurfaceTextureClient* c = getSelf(window); 64 return c->cancelBuffer(buffer); 65} 66 67int SurfaceTextureClient::lockBuffer(ANativeWindow* window, 68 ANativeWindowBuffer* buffer) { 69 SurfaceTextureClient* c = getSelf(window); 70 return c->lockBuffer(buffer); 71} 72 73int SurfaceTextureClient::queueBuffer(ANativeWindow* window, 74 ANativeWindowBuffer* buffer) { 75 SurfaceTextureClient* c = getSelf(window); 76 return c->queueBuffer(buffer); 77} 78 79int SurfaceTextureClient::query(const ANativeWindow* window, 80 int what, int* value) { 81 const SurfaceTextureClient* c = getSelf(window); 82 return c->query(what, value); 83} 84 85int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) { 86 va_list args; 87 va_start(args, operation); 88 SurfaceTextureClient* c = getSelf(window); 89 return c->perform(operation, args); 90} 91 92int SurfaceTextureClient::setSwapInterval(int interval) { 93 return INVALID_OPERATION; 94} 95 96int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { 97 LOGV("SurfaceTextureClient::dequeueBuffer"); 98 Mutex::Autolock lock(mMutex); 99 int buf = -1; 100 status_t err = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight, 101 mReqFormat, mReqUsage); 102 if (err < 0) { 103 LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)" 104 "failed: %d", err, mReqWidth, mReqHeight, mReqFormat, mReqUsage); 105 return err; 106 } 107 sp<GraphicBuffer>& gbuf(mSlots[buf]); 108 if (err == ISurfaceTexture::BUFFER_NEEDS_REALLOCATION || gbuf == 0) { 109 gbuf = mSurfaceTexture->requestBuffer(buf); 110 if (gbuf == 0) { 111 LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed"); 112 return NO_MEMORY; 113 } 114 mQueryWidth = gbuf->width; 115 mQueryHeight = gbuf->height; 116 mQueryFormat = gbuf->format; 117 } 118 *buffer = gbuf.get(); 119 return OK; 120} 121 122int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { 123 LOGV("SurfaceTextureClient::cancelBuffer"); 124 Mutex::Autolock lock(mMutex); 125 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 126 if (mSlots[i]->handle == buffer->handle) { 127 mSurfaceTexture->cancelBuffer(i); 128 return OK; 129 } 130 } 131 return BAD_VALUE; 132} 133 134int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) { 135 LOGV("SurfaceTextureClient::lockBuffer"); 136 Mutex::Autolock lock(mMutex); 137 return OK; 138} 139 140int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { 141 LOGV("SurfaceTextureClient::queueBuffer"); 142 Mutex::Autolock lock(mMutex); 143 int64_t timestamp; 144 if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) { 145 timestamp = systemTime(SYSTEM_TIME_MONOTONIC); 146 LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms", 147 timestamp / 1000000.f); 148 } else { 149 timestamp = mTimestamp; 150 } 151 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 152 if (mSlots[i]->handle == buffer->handle) { 153 return mSurfaceTexture->queueBuffer(i, timestamp); 154 } 155 } 156 LOGE("queueBuffer: unknown buffer queued"); 157 return BAD_VALUE; 158} 159 160int SurfaceTextureClient::query(int what, int* value) const { 161 LOGV("SurfaceTextureClient::query"); 162 switch (what) { 163 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: 164 // TODO: this is not needed anymore 165 *value = 0; 166 return NO_ERROR; 167 case NATIVE_WINDOW_CONCRETE_TYPE: 168 // TODO: this is not needed anymore 169 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; 170 return NO_ERROR; 171 } 172 return mSurfaceTexture->query(what, value); 173} 174 175int SurfaceTextureClient::perform(int operation, va_list args) 176{ 177 int res = NO_ERROR; 178 switch (operation) { 179 case NATIVE_WINDOW_CONNECT: 180 res = dispatchConnect(args); 181 break; 182 case NATIVE_WINDOW_DISCONNECT: 183 res = dispatchDisconnect(args); 184 break; 185 case NATIVE_WINDOW_SET_USAGE: 186 res = dispatchSetUsage(args); 187 break; 188 case NATIVE_WINDOW_SET_CROP: 189 res = dispatchSetCrop(args); 190 break; 191 case NATIVE_WINDOW_SET_BUFFER_COUNT: 192 res = dispatchSetBufferCount(args); 193 break; 194 case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: 195 res = dispatchSetBuffersGeometry(args); 196 break; 197 case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: 198 res = dispatchSetBuffersTransform(args); 199 break; 200 case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: 201 res = dispatchSetBuffersTimestamp(args); 202 break; 203 default: 204 res = NAME_NOT_FOUND; 205 break; 206 } 207 return res; 208} 209 210int SurfaceTextureClient::dispatchConnect(va_list args) { 211 int api = va_arg(args, int); 212 return connect(api); 213} 214 215int SurfaceTextureClient::dispatchDisconnect(va_list args) { 216 int api = va_arg(args, int); 217 return disconnect(api); 218} 219 220int SurfaceTextureClient::dispatchSetUsage(va_list args) { 221 int usage = va_arg(args, int); 222 return setUsage(usage); 223} 224 225int SurfaceTextureClient::dispatchSetCrop(va_list args) { 226 android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); 227 return setCrop(reinterpret_cast<Rect const*>(rect)); 228} 229 230int SurfaceTextureClient::dispatchSetBufferCount(va_list args) { 231 size_t bufferCount = va_arg(args, size_t); 232 return setBufferCount(bufferCount); 233} 234 235int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) { 236 int w = va_arg(args, int); 237 int h = va_arg(args, int); 238 int f = va_arg(args, int); 239 return setBuffersGeometry(w, h, f); 240} 241 242int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) { 243 int transform = va_arg(args, int); 244 return setBuffersTransform(transform); 245} 246 247int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) { 248 int64_t timestamp = va_arg(args, int64_t); 249 return setBuffersTimestamp(timestamp); 250} 251 252int SurfaceTextureClient::connect(int api) { 253 LOGV("SurfaceTextureClient::connect"); 254 Mutex::Autolock lock(mMutex); 255 int err = NO_ERROR; 256 switch (api) { 257 case NATIVE_WINDOW_API_EGL: 258 if (mConnectedApi) { 259 err = -EINVAL; 260 } else { 261 mConnectedApi = api; 262 } 263 break; 264 default: 265 err = -EINVAL; 266 break; 267 } 268 return err; 269} 270 271int SurfaceTextureClient::disconnect(int api) { 272 LOGV("SurfaceTextureClient::disconnect"); 273 Mutex::Autolock lock(mMutex); 274 int err = NO_ERROR; 275 switch (api) { 276 case NATIVE_WINDOW_API_EGL: 277 if (mConnectedApi == api) { 278 mConnectedApi = 0; 279 } else { 280 err = -EINVAL; 281 } 282 break; 283 default: 284 err = -EINVAL; 285 break; 286 } 287 return err; 288} 289 290int SurfaceTextureClient::getConnectedApi() const 291{ 292 Mutex::Autolock lock(mMutex); 293 return mConnectedApi; 294} 295 296 297int SurfaceTextureClient::setUsage(uint32_t reqUsage) 298{ 299 LOGV("SurfaceTextureClient::setUsage"); 300 Mutex::Autolock lock(mMutex); 301 mReqUsage = reqUsage; 302 return OK; 303} 304 305int SurfaceTextureClient::setCrop(Rect const* rect) 306{ 307 LOGV("SurfaceTextureClient::setCrop"); 308 Mutex::Autolock lock(mMutex); 309 310 Rect realRect; 311 if (rect == NULL || rect->isEmpty()) { 312 realRect = Rect(0, 0); 313 } else { 314 realRect = *rect; 315 } 316 317 status_t err = mSurfaceTexture->setCrop(*rect); 318 LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err)); 319 320 return err; 321} 322 323int SurfaceTextureClient::setBufferCount(int bufferCount) 324{ 325 LOGV("SurfaceTextureClient::setBufferCount"); 326 Mutex::Autolock lock(mMutex); 327 328 status_t err = mSurfaceTexture->setBufferCount(bufferCount); 329 LOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s", 330 bufferCount, strerror(-err)); 331 332 if (err == NO_ERROR) { 333 freeAllBuffers(); 334 } 335 336 return err; 337} 338 339int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format) 340{ 341 LOGV("SurfaceTextureClient::setBuffersGeometry"); 342 Mutex::Autolock lock(mMutex); 343 344 if (w<0 || h<0 || format<0) 345 return BAD_VALUE; 346 347 if ((w && !h) || (!w && h)) 348 return BAD_VALUE; 349 350 mReqWidth = w; 351 mReqHeight = h; 352 mReqFormat = format; 353 354 status_t err = mSurfaceTexture->setCrop(Rect(0, 0)); 355 LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", strerror(-err)); 356 357 return err; 358} 359 360int SurfaceTextureClient::setBuffersTransform(int transform) 361{ 362 LOGV("SurfaceTextureClient::setBuffersTransform"); 363 Mutex::Autolock lock(mMutex); 364 status_t err = mSurfaceTexture->setTransform(transform); 365 return err; 366} 367 368int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp) 369{ 370 LOGV("SurfaceTextureClient::setBuffersTimestamp"); 371 Mutex::Autolock lock(mMutex); 372 mTimestamp = timestamp; 373 return NO_ERROR; 374} 375 376void SurfaceTextureClient::freeAllBuffers() { 377 for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 378 mSlots[i] = 0; 379 } 380} 381 382}; // namespace android 383