Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright (C) 2010 The Android Open Source Project |
michael@0 | 3 | * Copyright (C) 2013 Mozilla Foundation |
michael@0 | 4 | * |
michael@0 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
michael@0 | 6 | * you may not use this file except in compliance with the License. |
michael@0 | 7 | * You may obtain a copy of the License at |
michael@0 | 8 | * |
michael@0 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
michael@0 | 10 | * |
michael@0 | 11 | * Unless required by applicable law or agreed to in writing, software |
michael@0 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
michael@0 | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
michael@0 | 14 | * See the License for the specific language governing permissions and |
michael@0 | 15 | * limitations under the License. |
michael@0 | 16 | */ |
michael@0 | 17 | |
michael@0 | 18 | #define LOG_TAG "GonkNativeWindowClient" |
michael@0 | 19 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS |
michael@0 | 20 | //#define LOG_NDEBUG 0 |
michael@0 | 21 | |
michael@0 | 22 | #include <android/native_window.h> |
michael@0 | 23 | |
michael@0 | 24 | #include <binder/Parcel.h> |
michael@0 | 25 | |
michael@0 | 26 | #include <utils/Log.h> |
michael@0 | 27 | #include <utils/Trace.h> |
michael@0 | 28 | |
michael@0 | 29 | #include <ui/Fence.h> |
michael@0 | 30 | |
michael@0 | 31 | #include "GonkNativeWindowClientKK.h" |
michael@0 | 32 | |
michael@0 | 33 | namespace android { |
michael@0 | 34 | |
michael@0 | 35 | GonkNativeWindowClient::GonkNativeWindowClient( |
michael@0 | 36 | const sp<IGraphicBufferProducer>& bufferProducer, |
michael@0 | 37 | bool controlledByApp) |
michael@0 | 38 | : mGraphicBufferProducer(bufferProducer) |
michael@0 | 39 | { |
michael@0 | 40 | // Initialize the ANativeWindow function pointers. |
michael@0 | 41 | ANativeWindow::setSwapInterval = hook_setSwapInterval; |
michael@0 | 42 | ANativeWindow::dequeueBuffer = hook_dequeueBuffer; |
michael@0 | 43 | ANativeWindow::cancelBuffer = hook_cancelBuffer; |
michael@0 | 44 | ANativeWindow::queueBuffer = hook_queueBuffer; |
michael@0 | 45 | ANativeWindow::query = hook_query; |
michael@0 | 46 | ANativeWindow::perform = hook_perform; |
michael@0 | 47 | |
michael@0 | 48 | ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED; |
michael@0 | 49 | ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED; |
michael@0 | 50 | ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED; |
michael@0 | 51 | ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED; |
michael@0 | 52 | |
michael@0 | 53 | const_cast<int&>(ANativeWindow::minSwapInterval) = 0; |
michael@0 | 54 | const_cast<int&>(ANativeWindow::maxSwapInterval) = 1; |
michael@0 | 55 | |
michael@0 | 56 | mReqWidth = 0; |
michael@0 | 57 | mReqHeight = 0; |
michael@0 | 58 | mReqFormat = 0; |
michael@0 | 59 | mReqUsage = 0; |
michael@0 | 60 | mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO; |
michael@0 | 61 | mCrop.clear(); |
michael@0 | 62 | mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; |
michael@0 | 63 | mTransform = 0; |
michael@0 | 64 | mDefaultWidth = 0; |
michael@0 | 65 | mDefaultHeight = 0; |
michael@0 | 66 | mUserWidth = 0; |
michael@0 | 67 | mUserHeight = 0; |
michael@0 | 68 | mTransformHint = 0; |
michael@0 | 69 | mConsumerRunningBehind = false; |
michael@0 | 70 | mConnectedToCpu = false; |
michael@0 | 71 | mProducerControlledByApp = controlledByApp; |
michael@0 | 72 | mSwapIntervalZero = false; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | GonkNativeWindowClient::~GonkNativeWindowClient() { |
michael@0 | 76 | if (mConnectedToCpu) { |
michael@0 | 77 | GonkNativeWindowClient::disconnect(NATIVE_WINDOW_API_CPU); |
michael@0 | 78 | } |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | sp<IGraphicBufferProducer> GonkNativeWindowClient::getIGraphicBufferProducer() const { |
michael@0 | 82 | return mGraphicBufferProducer; |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | int GonkNativeWindowClient::hook_setSwapInterval(ANativeWindow* window, int interval) { |
michael@0 | 86 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 87 | return c->setSwapInterval(interval); |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | int GonkNativeWindowClient::hook_dequeueBuffer(ANativeWindow* window, |
michael@0 | 91 | ANativeWindowBuffer** buffer, int* fenceFd) { |
michael@0 | 92 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 93 | return c->dequeueBuffer(buffer, fenceFd); |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | int GonkNativeWindowClient::hook_cancelBuffer(ANativeWindow* window, |
michael@0 | 97 | ANativeWindowBuffer* buffer, int fenceFd) { |
michael@0 | 98 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 99 | return c->cancelBuffer(buffer, fenceFd); |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | int GonkNativeWindowClient::hook_queueBuffer(ANativeWindow* window, |
michael@0 | 103 | ANativeWindowBuffer* buffer, int fenceFd) { |
michael@0 | 104 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 105 | return c->queueBuffer(buffer, fenceFd); |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | int GonkNativeWindowClient::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, |
michael@0 | 109 | ANativeWindowBuffer** buffer) { |
michael@0 | 110 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 111 | ANativeWindowBuffer* buf; |
michael@0 | 112 | int fenceFd = -1; |
michael@0 | 113 | int result = c->dequeueBuffer(&buf, &fenceFd); |
michael@0 | 114 | sp<Fence> fence(new Fence(fenceFd)); |
michael@0 | 115 | int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED"); |
michael@0 | 116 | if (waitResult != OK) { |
michael@0 | 117 | ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d", |
michael@0 | 118 | waitResult); |
michael@0 | 119 | c->cancelBuffer(buf, -1); |
michael@0 | 120 | return waitResult; |
michael@0 | 121 | } |
michael@0 | 122 | *buffer = buf; |
michael@0 | 123 | return result; |
michael@0 | 124 | } |
michael@0 | 125 | |
michael@0 | 126 | int GonkNativeWindowClient::hook_cancelBuffer_DEPRECATED(ANativeWindow* window, |
michael@0 | 127 | ANativeWindowBuffer* buffer) { |
michael@0 | 128 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 129 | return c->cancelBuffer(buffer, -1); |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | int GonkNativeWindowClient::hook_lockBuffer_DEPRECATED(ANativeWindow* window, |
michael@0 | 133 | ANativeWindowBuffer* buffer) { |
michael@0 | 134 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 135 | return c->lockBuffer_DEPRECATED(buffer); |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | int GonkNativeWindowClient::hook_queueBuffer_DEPRECATED(ANativeWindow* window, |
michael@0 | 139 | ANativeWindowBuffer* buffer) { |
michael@0 | 140 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 141 | return c->queueBuffer(buffer, -1); |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | int GonkNativeWindowClient::hook_query(const ANativeWindow* window, |
michael@0 | 145 | int what, int* value) { |
michael@0 | 146 | const GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 147 | return c->query(what, value); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | int GonkNativeWindowClient::hook_perform(ANativeWindow* window, int operation, ...) { |
michael@0 | 151 | va_list args; |
michael@0 | 152 | va_start(args, operation); |
michael@0 | 153 | GonkNativeWindowClient* c = getSelf(window); |
michael@0 | 154 | return c->perform(operation, args); |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | int GonkNativeWindowClient::setSwapInterval(int interval) { |
michael@0 | 158 | ATRACE_CALL(); |
michael@0 | 159 | // EGL specification states: |
michael@0 | 160 | // interval is silently clamped to minimum and maximum implementation |
michael@0 | 161 | // dependent values before being stored. |
michael@0 | 162 | |
michael@0 | 163 | if (interval < minSwapInterval) |
michael@0 | 164 | interval = minSwapInterval; |
michael@0 | 165 | |
michael@0 | 166 | if (interval > maxSwapInterval) |
michael@0 | 167 | interval = maxSwapInterval; |
michael@0 | 168 | |
michael@0 | 169 | return NO_ERROR; |
michael@0 | 170 | } |
michael@0 | 171 | |
michael@0 | 172 | int GonkNativeWindowClient::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { |
michael@0 | 173 | ATRACE_CALL(); |
michael@0 | 174 | ALOGV("GonkNativeWindowClient::dequeueBuffer"); |
michael@0 | 175 | Mutex::Autolock lock(mMutex); |
michael@0 | 176 | int buf = -1; |
michael@0 | 177 | int reqW = mReqWidth ? mReqWidth : mUserWidth; |
michael@0 | 178 | int reqH = mReqHeight ? mReqHeight : mUserHeight; |
michael@0 | 179 | sp<Fence> fence; |
michael@0 | 180 | status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero, |
michael@0 | 181 | reqW, reqH, mReqFormat, mReqUsage); |
michael@0 | 182 | if (result < 0) { |
michael@0 | 183 | ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)" |
michael@0 | 184 | "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage, |
michael@0 | 185 | result); |
michael@0 | 186 | return result; |
michael@0 | 187 | } |
michael@0 | 188 | sp<GraphicBuffer>& gbuf(mSlots[buf].buffer); |
michael@0 | 189 | |
michael@0 | 190 | // this should never happen |
michael@0 | 191 | ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); |
michael@0 | 192 | |
michael@0 | 193 | if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) { |
michael@0 | 194 | freeAllBuffers(); |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) { |
michael@0 | 198 | result = mGraphicBufferProducer->requestBuffer(buf, &gbuf); |
michael@0 | 199 | if (result != NO_ERROR) { |
michael@0 | 200 | ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result); |
michael@0 | 201 | return result; |
michael@0 | 202 | } |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | if (fence->isValid()) { |
michael@0 | 206 | *fenceFd = fence->dup(); |
michael@0 | 207 | if (*fenceFd == -1) { |
michael@0 | 208 | ALOGE("dequeueBuffer: error duping fence: %d", errno); |
michael@0 | 209 | // dup() should never fail; something is badly wrong. Soldier on |
michael@0 | 210 | // and hope for the best; the worst that should happen is some |
michael@0 | 211 | // visible corruption that lasts until the next frame. |
michael@0 | 212 | } |
michael@0 | 213 | } else { |
michael@0 | 214 | *fenceFd = -1; |
michael@0 | 215 | } |
michael@0 | 216 | |
michael@0 | 217 | *buffer = gbuf.get(); |
michael@0 | 218 | return OK; |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | int GonkNativeWindowClient::cancelBuffer(android_native_buffer_t* buffer, |
michael@0 | 222 | int fenceFd) { |
michael@0 | 223 | ATRACE_CALL(); |
michael@0 | 224 | ALOGV("GonkNativeWindowClient::cancelBuffer"); |
michael@0 | 225 | Mutex::Autolock lock(mMutex); |
michael@0 | 226 | int i = getSlotFromBufferLocked(buffer); |
michael@0 | 227 | if (i < 0) { |
michael@0 | 228 | return i; |
michael@0 | 229 | } |
michael@0 | 230 | sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); |
michael@0 | 231 | mGraphicBufferProducer->cancelBuffer(i, fence); |
michael@0 | 232 | return OK; |
michael@0 | 233 | } |
michael@0 | 234 | |
michael@0 | 235 | int GonkNativeWindowClient::getSlotFromBufferLocked( |
michael@0 | 236 | android_native_buffer_t* buffer) const { |
michael@0 | 237 | bool dumpedState = false; |
michael@0 | 238 | for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { |
michael@0 | 239 | if (mSlots[i].buffer != NULL && |
michael@0 | 240 | mSlots[i].buffer->handle == buffer->handle) { |
michael@0 | 241 | return i; |
michael@0 | 242 | } |
michael@0 | 243 | } |
michael@0 | 244 | ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle); |
michael@0 | 245 | return BAD_VALUE; |
michael@0 | 246 | } |
michael@0 | 247 | |
michael@0 | 248 | int GonkNativeWindowClient::lockBuffer_DEPRECATED(android_native_buffer_t* buffer) { |
michael@0 | 249 | ALOGV("GonkNativeWindowClient::lockBuffer"); |
michael@0 | 250 | Mutex::Autolock lock(mMutex); |
michael@0 | 251 | return OK; |
michael@0 | 252 | } |
michael@0 | 253 | |
michael@0 | 254 | int GonkNativeWindowClient::queueBuffer(android_native_buffer_t* buffer, int fenceFd) { |
michael@0 | 255 | ATRACE_CALL(); |
michael@0 | 256 | ALOGV("GonkNativeWindowClient::queueBuffer"); |
michael@0 | 257 | Mutex::Autolock lock(mMutex); |
michael@0 | 258 | int64_t timestamp; |
michael@0 | 259 | bool isAutoTimestamp = false; |
michael@0 | 260 | if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) { |
michael@0 | 261 | timestamp = systemTime(SYSTEM_TIME_MONOTONIC); |
michael@0 | 262 | isAutoTimestamp = true; |
michael@0 | 263 | ALOGV("GonkNativeWindowClient::queueBuffer making up timestamp: %.2f ms", |
michael@0 | 264 | timestamp / 1000000.f); |
michael@0 | 265 | } else { |
michael@0 | 266 | timestamp = mTimestamp; |
michael@0 | 267 | } |
michael@0 | 268 | int i = getSlotFromBufferLocked(buffer); |
michael@0 | 269 | if (i < 0) { |
michael@0 | 270 | return i; |
michael@0 | 271 | } |
michael@0 | 272 | |
michael@0 | 273 | |
michael@0 | 274 | // Make sure the crop rectangle is entirely inside the buffer. |
michael@0 | 275 | Rect crop; |
michael@0 | 276 | mCrop.intersect(Rect(buffer->width, buffer->height), &crop); |
michael@0 | 277 | |
michael@0 | 278 | sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE); |
michael@0 | 279 | IGraphicBufferProducer::QueueBufferOutput output; |
michael@0 | 280 | IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp, |
michael@0 | 281 | crop, mScalingMode, mTransform, mSwapIntervalZero, fence); |
michael@0 | 282 | status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output); |
michael@0 | 283 | if (err != OK) { |
michael@0 | 284 | ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); |
michael@0 | 285 | } |
michael@0 | 286 | uint32_t numPendingBuffers = 0; |
michael@0 | 287 | output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, |
michael@0 | 288 | &numPendingBuffers); |
michael@0 | 289 | |
michael@0 | 290 | mConsumerRunningBehind = (numPendingBuffers >= 2); |
michael@0 | 291 | |
michael@0 | 292 | return err; |
michael@0 | 293 | } |
michael@0 | 294 | |
michael@0 | 295 | int GonkNativeWindowClient::query(int what, int* value) const { |
michael@0 | 296 | ATRACE_CALL(); |
michael@0 | 297 | ALOGV("GonkNativeWindowClient::query"); |
michael@0 | 298 | { // scope for the lock |
michael@0 | 299 | Mutex::Autolock lock(mMutex); |
michael@0 | 300 | switch (what) { |
michael@0 | 301 | case NATIVE_WINDOW_FORMAT: |
michael@0 | 302 | if (mReqFormat) { |
michael@0 | 303 | *value = mReqFormat; |
michael@0 | 304 | return NO_ERROR; |
michael@0 | 305 | } |
michael@0 | 306 | break; |
michael@0 | 307 | case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: { |
michael@0 | 308 | //sp<ISurfaceComposer> composer( |
michael@0 | 309 | // ComposerService::getComposerService()); |
michael@0 | 310 | //if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) { |
michael@0 | 311 | // *value = 1; |
michael@0 | 312 | //} else { |
michael@0 | 313 | *value = 0; |
michael@0 | 314 | //} |
michael@0 | 315 | return NO_ERROR; |
michael@0 | 316 | } |
michael@0 | 317 | case NATIVE_WINDOW_CONCRETE_TYPE: |
michael@0 | 318 | *value = NATIVE_WINDOW_SURFACE; |
michael@0 | 319 | return NO_ERROR; |
michael@0 | 320 | case NATIVE_WINDOW_DEFAULT_WIDTH: |
michael@0 | 321 | *value = mUserWidth ? mUserWidth : mDefaultWidth; |
michael@0 | 322 | return NO_ERROR; |
michael@0 | 323 | case NATIVE_WINDOW_DEFAULT_HEIGHT: |
michael@0 | 324 | *value = mUserHeight ? mUserHeight : mDefaultHeight; |
michael@0 | 325 | return NO_ERROR; |
michael@0 | 326 | case NATIVE_WINDOW_TRANSFORM_HINT: |
michael@0 | 327 | *value = mTransformHint; |
michael@0 | 328 | return NO_ERROR; |
michael@0 | 329 | case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: { |
michael@0 | 330 | status_t err = NO_ERROR; |
michael@0 | 331 | if (!mConsumerRunningBehind) { |
michael@0 | 332 | *value = 0; |
michael@0 | 333 | } else { |
michael@0 | 334 | err = mGraphicBufferProducer->query(what, value); |
michael@0 | 335 | if (err == NO_ERROR) { |
michael@0 | 336 | mConsumerRunningBehind = *value; |
michael@0 | 337 | } |
michael@0 | 338 | } |
michael@0 | 339 | return err; |
michael@0 | 340 | } |
michael@0 | 341 | } |
michael@0 | 342 | } |
michael@0 | 343 | return mGraphicBufferProducer->query(what, value); |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | int GonkNativeWindowClient::perform(int operation, va_list args) |
michael@0 | 347 | { |
michael@0 | 348 | int res = NO_ERROR; |
michael@0 | 349 | switch (operation) { |
michael@0 | 350 | case NATIVE_WINDOW_CONNECT: |
michael@0 | 351 | // deprecated. must return NO_ERROR. |
michael@0 | 352 | break; |
michael@0 | 353 | case NATIVE_WINDOW_DISCONNECT: |
michael@0 | 354 | // deprecated. must return NO_ERROR. |
michael@0 | 355 | break; |
michael@0 | 356 | case NATIVE_WINDOW_SET_USAGE: |
michael@0 | 357 | res = dispatchSetUsage(args); |
michael@0 | 358 | break; |
michael@0 | 359 | case NATIVE_WINDOW_SET_CROP: |
michael@0 | 360 | res = dispatchSetCrop(args); |
michael@0 | 361 | break; |
michael@0 | 362 | case NATIVE_WINDOW_SET_BUFFER_COUNT: |
michael@0 | 363 | res = dispatchSetBufferCount(args); |
michael@0 | 364 | break; |
michael@0 | 365 | case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: |
michael@0 | 366 | res = dispatchSetBuffersGeometry(args); |
michael@0 | 367 | break; |
michael@0 | 368 | case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: |
michael@0 | 369 | res = dispatchSetBuffersTransform(args); |
michael@0 | 370 | break; |
michael@0 | 371 | case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP: |
michael@0 | 372 | res = dispatchSetBuffersTimestamp(args); |
michael@0 | 373 | break; |
michael@0 | 374 | case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: |
michael@0 | 375 | res = dispatchSetBuffersDimensions(args); |
michael@0 | 376 | break; |
michael@0 | 377 | case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS: |
michael@0 | 378 | res = dispatchSetBuffersUserDimensions(args); |
michael@0 | 379 | break; |
michael@0 | 380 | case NATIVE_WINDOW_SET_BUFFERS_FORMAT: |
michael@0 | 381 | res = dispatchSetBuffersFormat(args); |
michael@0 | 382 | break; |
michael@0 | 383 | case NATIVE_WINDOW_LOCK: |
michael@0 | 384 | res = dispatchLock(args); |
michael@0 | 385 | break; |
michael@0 | 386 | case NATIVE_WINDOW_UNLOCK_AND_POST: |
michael@0 | 387 | res = dispatchUnlockAndPost(args); |
michael@0 | 388 | break; |
michael@0 | 389 | case NATIVE_WINDOW_SET_SCALING_MODE: |
michael@0 | 390 | res = dispatchSetScalingMode(args); |
michael@0 | 391 | break; |
michael@0 | 392 | case NATIVE_WINDOW_API_CONNECT: |
michael@0 | 393 | res = dispatchConnect(args); |
michael@0 | 394 | break; |
michael@0 | 395 | case NATIVE_WINDOW_API_DISCONNECT: |
michael@0 | 396 | res = dispatchDisconnect(args); |
michael@0 | 397 | break; |
michael@0 | 398 | default: |
michael@0 | 399 | res = NAME_NOT_FOUND; |
michael@0 | 400 | break; |
michael@0 | 401 | } |
michael@0 | 402 | return res; |
michael@0 | 403 | } |
michael@0 | 404 | |
michael@0 | 405 | int GonkNativeWindowClient::dispatchConnect(va_list args) { |
michael@0 | 406 | int api = va_arg(args, int); |
michael@0 | 407 | return connect(api); |
michael@0 | 408 | } |
michael@0 | 409 | |
michael@0 | 410 | int GonkNativeWindowClient::dispatchDisconnect(va_list args) { |
michael@0 | 411 | int api = va_arg(args, int); |
michael@0 | 412 | return disconnect(api); |
michael@0 | 413 | } |
michael@0 | 414 | |
michael@0 | 415 | int GonkNativeWindowClient::dispatchSetUsage(va_list args) { |
michael@0 | 416 | int usage = va_arg(args, int); |
michael@0 | 417 | return setUsage(usage); |
michael@0 | 418 | } |
michael@0 | 419 | |
michael@0 | 420 | int GonkNativeWindowClient::dispatchSetCrop(va_list args) { |
michael@0 | 421 | android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); |
michael@0 | 422 | return setCrop(reinterpret_cast<Rect const*>(rect)); |
michael@0 | 423 | } |
michael@0 | 424 | |
michael@0 | 425 | int GonkNativeWindowClient::dispatchSetBufferCount(va_list args) { |
michael@0 | 426 | size_t bufferCount = va_arg(args, size_t); |
michael@0 | 427 | return setBufferCount(bufferCount); |
michael@0 | 428 | } |
michael@0 | 429 | |
michael@0 | 430 | int GonkNativeWindowClient::dispatchSetBuffersGeometry(va_list args) { |
michael@0 | 431 | int w = va_arg(args, int); |
michael@0 | 432 | int h = va_arg(args, int); |
michael@0 | 433 | int f = va_arg(args, int); |
michael@0 | 434 | int err = setBuffersDimensions(w, h); |
michael@0 | 435 | if (err != 0) { |
michael@0 | 436 | return err; |
michael@0 | 437 | } |
michael@0 | 438 | return setBuffersFormat(f); |
michael@0 | 439 | } |
michael@0 | 440 | |
michael@0 | 441 | int GonkNativeWindowClient::dispatchSetBuffersDimensions(va_list args) { |
michael@0 | 442 | int w = va_arg(args, int); |
michael@0 | 443 | int h = va_arg(args, int); |
michael@0 | 444 | return setBuffersDimensions(w, h); |
michael@0 | 445 | } |
michael@0 | 446 | |
michael@0 | 447 | int GonkNativeWindowClient::dispatchSetBuffersUserDimensions(va_list args) { |
michael@0 | 448 | int w = va_arg(args, int); |
michael@0 | 449 | int h = va_arg(args, int); |
michael@0 | 450 | return setBuffersUserDimensions(w, h); |
michael@0 | 451 | } |
michael@0 | 452 | |
michael@0 | 453 | int GonkNativeWindowClient::dispatchSetBuffersFormat(va_list args) { |
michael@0 | 454 | int f = va_arg(args, int); |
michael@0 | 455 | return setBuffersFormat(f); |
michael@0 | 456 | } |
michael@0 | 457 | |
michael@0 | 458 | int GonkNativeWindowClient::dispatchSetScalingMode(va_list args) { |
michael@0 | 459 | int m = va_arg(args, int); |
michael@0 | 460 | return setScalingMode(m); |
michael@0 | 461 | } |
michael@0 | 462 | |
michael@0 | 463 | int GonkNativeWindowClient::dispatchSetBuffersTransform(va_list args) { |
michael@0 | 464 | int transform = va_arg(args, int); |
michael@0 | 465 | return setBuffersTransform(transform); |
michael@0 | 466 | } |
michael@0 | 467 | |
michael@0 | 468 | int GonkNativeWindowClient::dispatchSetBuffersTimestamp(va_list args) { |
michael@0 | 469 | int64_t timestamp = va_arg(args, int64_t); |
michael@0 | 470 | return setBuffersTimestamp(timestamp); |
michael@0 | 471 | } |
michael@0 | 472 | |
michael@0 | 473 | int GonkNativeWindowClient::dispatchLock(va_list args) { |
michael@0 | 474 | ANativeWindow_Buffer* outBuffer = va_arg(args, ANativeWindow_Buffer*); |
michael@0 | 475 | ARect* inOutDirtyBounds = va_arg(args, ARect*); |
michael@0 | 476 | return lock(outBuffer, inOutDirtyBounds); |
michael@0 | 477 | } |
michael@0 | 478 | |
michael@0 | 479 | int GonkNativeWindowClient::dispatchUnlockAndPost(va_list args) { |
michael@0 | 480 | return unlockAndPost(); |
michael@0 | 481 | } |
michael@0 | 482 | |
michael@0 | 483 | |
michael@0 | 484 | int GonkNativeWindowClient::connect(int api) { |
michael@0 | 485 | ATRACE_CALL(); |
michael@0 | 486 | ALOGV("GonkNativeWindowClient::connect"); |
michael@0 | 487 | static sp<BBinder> sLife = new BBinder(); |
michael@0 | 488 | Mutex::Autolock lock(mMutex); |
michael@0 | 489 | IGraphicBufferProducer::QueueBufferOutput output; |
michael@0 | 490 | int err = mGraphicBufferProducer->connect(sLife, api, true, &output); |
michael@0 | 491 | if (err == NO_ERROR) { |
michael@0 | 492 | uint32_t numPendingBuffers = 0; |
michael@0 | 493 | output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint, |
michael@0 | 494 | &numPendingBuffers); |
michael@0 | 495 | mConsumerRunningBehind = (numPendingBuffers >= 2); |
michael@0 | 496 | } |
michael@0 | 497 | if (!err && api == NATIVE_WINDOW_API_CPU) { |
michael@0 | 498 | mConnectedToCpu = true; |
michael@0 | 499 | } |
michael@0 | 500 | return err; |
michael@0 | 501 | } |
michael@0 | 502 | |
michael@0 | 503 | |
michael@0 | 504 | int GonkNativeWindowClient::disconnect(int api) { |
michael@0 | 505 | ATRACE_CALL(); |
michael@0 | 506 | ALOGV("GonkNativeWindowClient::disconnect"); |
michael@0 | 507 | Mutex::Autolock lock(mMutex); |
michael@0 | 508 | freeAllBuffers(); |
michael@0 | 509 | int err = mGraphicBufferProducer->disconnect(api); |
michael@0 | 510 | if (!err) { |
michael@0 | 511 | mReqFormat = 0; |
michael@0 | 512 | mReqWidth = 0; |
michael@0 | 513 | mReqHeight = 0; |
michael@0 | 514 | mReqUsage = 0; |
michael@0 | 515 | mCrop.clear(); |
michael@0 | 516 | mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; |
michael@0 | 517 | mTransform = 0; |
michael@0 | 518 | if (api == NATIVE_WINDOW_API_CPU) { |
michael@0 | 519 | mConnectedToCpu = false; |
michael@0 | 520 | } |
michael@0 | 521 | } |
michael@0 | 522 | return err; |
michael@0 | 523 | } |
michael@0 | 524 | |
michael@0 | 525 | int GonkNativeWindowClient::setUsage(uint32_t reqUsage) |
michael@0 | 526 | { |
michael@0 | 527 | ALOGV("GonkNativeWindowClient::setUsage"); |
michael@0 | 528 | Mutex::Autolock lock(mMutex); |
michael@0 | 529 | mReqUsage = reqUsage; |
michael@0 | 530 | return OK; |
michael@0 | 531 | } |
michael@0 | 532 | |
michael@0 | 533 | int GonkNativeWindowClient::setCrop(Rect const* rect) |
michael@0 | 534 | { |
michael@0 | 535 | ATRACE_CALL(); |
michael@0 | 536 | |
michael@0 | 537 | Rect realRect; |
michael@0 | 538 | if (rect == NULL || rect->isEmpty()) { |
michael@0 | 539 | realRect.clear(); |
michael@0 | 540 | } else { |
michael@0 | 541 | realRect = *rect; |
michael@0 | 542 | } |
michael@0 | 543 | |
michael@0 | 544 | ALOGV("GonkNativeWindowClient::setCrop rect=[%d %d %d %d]", |
michael@0 | 545 | realRect.left, realRect.top, realRect.right, realRect.bottom); |
michael@0 | 546 | |
michael@0 | 547 | Mutex::Autolock lock(mMutex); |
michael@0 | 548 | mCrop = realRect; |
michael@0 | 549 | return NO_ERROR; |
michael@0 | 550 | } |
michael@0 | 551 | |
michael@0 | 552 | int GonkNativeWindowClient::setBufferCount(int bufferCount) |
michael@0 | 553 | { |
michael@0 | 554 | ATRACE_CALL(); |
michael@0 | 555 | ALOGV("GonkNativeWindowClient::setBufferCount"); |
michael@0 | 556 | Mutex::Autolock lock(mMutex); |
michael@0 | 557 | |
michael@0 | 558 | status_t err = mGraphicBufferProducer->setBufferCount(bufferCount); |
michael@0 | 559 | ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s", |
michael@0 | 560 | bufferCount, strerror(-err)); |
michael@0 | 561 | |
michael@0 | 562 | if (err == NO_ERROR) { |
michael@0 | 563 | freeAllBuffers(); |
michael@0 | 564 | } |
michael@0 | 565 | |
michael@0 | 566 | return err; |
michael@0 | 567 | } |
michael@0 | 568 | |
michael@0 | 569 | int GonkNativeWindowClient::setBuffersDimensions(int w, int h) |
michael@0 | 570 | { |
michael@0 | 571 | ATRACE_CALL(); |
michael@0 | 572 | ALOGV("GonkNativeWindowClient::setBuffersDimensions"); |
michael@0 | 573 | |
michael@0 | 574 | if (w<0 || h<0) |
michael@0 | 575 | return BAD_VALUE; |
michael@0 | 576 | |
michael@0 | 577 | if ((w && !h) || (!w && h)) |
michael@0 | 578 | return BAD_VALUE; |
michael@0 | 579 | |
michael@0 | 580 | Mutex::Autolock lock(mMutex); |
michael@0 | 581 | mReqWidth = w; |
michael@0 | 582 | mReqHeight = h; |
michael@0 | 583 | return NO_ERROR; |
michael@0 | 584 | } |
michael@0 | 585 | |
michael@0 | 586 | int GonkNativeWindowClient::setBuffersUserDimensions(int w, int h) |
michael@0 | 587 | { |
michael@0 | 588 | ATRACE_CALL(); |
michael@0 | 589 | ALOGV("GonkNativeWindowClient::setBuffersUserDimensions"); |
michael@0 | 590 | |
michael@0 | 591 | if (w<0 || h<0) |
michael@0 | 592 | return BAD_VALUE; |
michael@0 | 593 | |
michael@0 | 594 | if ((w && !h) || (!w && h)) |
michael@0 | 595 | return BAD_VALUE; |
michael@0 | 596 | |
michael@0 | 597 | Mutex::Autolock lock(mMutex); |
michael@0 | 598 | mUserWidth = w; |
michael@0 | 599 | mUserHeight = h; |
michael@0 | 600 | return NO_ERROR; |
michael@0 | 601 | } |
michael@0 | 602 | |
michael@0 | 603 | int GonkNativeWindowClient::setBuffersFormat(int format) |
michael@0 | 604 | { |
michael@0 | 605 | ALOGV("GonkNativeWindowClient::setBuffersFormat"); |
michael@0 | 606 | |
michael@0 | 607 | if (format<0) |
michael@0 | 608 | return BAD_VALUE; |
michael@0 | 609 | |
michael@0 | 610 | Mutex::Autolock lock(mMutex); |
michael@0 | 611 | mReqFormat = format; |
michael@0 | 612 | return NO_ERROR; |
michael@0 | 613 | } |
michael@0 | 614 | |
michael@0 | 615 | int GonkNativeWindowClient::setScalingMode(int mode) |
michael@0 | 616 | { |
michael@0 | 617 | ATRACE_CALL(); |
michael@0 | 618 | ALOGV("GonkNativeWindowClient::setScalingMode(%d)", mode); |
michael@0 | 619 | |
michael@0 | 620 | switch (mode) { |
michael@0 | 621 | case NATIVE_WINDOW_SCALING_MODE_FREEZE: |
michael@0 | 622 | case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: |
michael@0 | 623 | case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: |
michael@0 | 624 | break; |
michael@0 | 625 | default: |
michael@0 | 626 | ALOGE("unknown scaling mode: %d", mode); |
michael@0 | 627 | return BAD_VALUE; |
michael@0 | 628 | } |
michael@0 | 629 | |
michael@0 | 630 | Mutex::Autolock lock(mMutex); |
michael@0 | 631 | mScalingMode = mode; |
michael@0 | 632 | return NO_ERROR; |
michael@0 | 633 | } |
michael@0 | 634 | |
michael@0 | 635 | int GonkNativeWindowClient::setBuffersTransform(int transform) |
michael@0 | 636 | { |
michael@0 | 637 | ATRACE_CALL(); |
michael@0 | 638 | ALOGV("GonkNativeWindowClient::setBuffersTransform"); |
michael@0 | 639 | Mutex::Autolock lock(mMutex); |
michael@0 | 640 | mTransform = transform; |
michael@0 | 641 | return NO_ERROR; |
michael@0 | 642 | } |
michael@0 | 643 | |
michael@0 | 644 | int GonkNativeWindowClient::setBuffersTimestamp(int64_t timestamp) |
michael@0 | 645 | { |
michael@0 | 646 | ALOGV("GonkNativeWindowClient::setBuffersTimestamp"); |
michael@0 | 647 | Mutex::Autolock lock(mMutex); |
michael@0 | 648 | mTimestamp = timestamp; |
michael@0 | 649 | return NO_ERROR; |
michael@0 | 650 | } |
michael@0 | 651 | |
michael@0 | 652 | void GonkNativeWindowClient::freeAllBuffers() { |
michael@0 | 653 | for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { |
michael@0 | 654 | mSlots[i].buffer = 0; |
michael@0 | 655 | } |
michael@0 | 656 | } |
michael@0 | 657 | |
michael@0 | 658 | // ---------------------------------------------------------------------- |
michael@0 | 659 | // the lock/unlock APIs must be used from the same thread |
michael@0 | 660 | |
michael@0 | 661 | // ---------------------------------------------------------------------------- |
michael@0 | 662 | |
michael@0 | 663 | status_t GonkNativeWindowClient::lock( |
michael@0 | 664 | ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) |
michael@0 | 665 | { |
michael@0 | 666 | return INVALID_OPERATION; |
michael@0 | 667 | } |
michael@0 | 668 | |
michael@0 | 669 | status_t GonkNativeWindowClient::unlockAndPost() |
michael@0 | 670 | { |
michael@0 | 671 | return INVALID_OPERATION; |
michael@0 | 672 | } |
michael@0 | 673 | |
michael@0 | 674 | }; // namespace android |