1 /* 2 * Copyright (C) 2013 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 "RenderScript.h" 18 #include "rsCppInternal.h" 19 20 using namespace android; 21 using namespace RSC; 22 23 24 void * Allocation::getIDSafe() const { 25 return getID(); 26 } 27 28 void Allocation::updateCacheInfo(sp<const Type> t) { 29 mCurrentDimX = t->getX(); 30 mCurrentDimY = t->getY(); 31 mCurrentDimZ = t->getZ(); 32 mCurrentCount = mCurrentDimX; 33 if (mCurrentDimY > 1) { 34 mCurrentCount *= mCurrentDimY; 35 } 36 if (mCurrentDimZ > 1) { 37 mCurrentCount *= mCurrentDimZ; 38 } 39 } 40 41 Allocation::Allocation(void *id, sp<RS> rs, sp<const Type> t, uint32_t usage) : 42 BaseObj(id, rs), mSelectedY(0), mSelectedZ(0), mSelectedLOD(0), 43 mSelectedFace(RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X) { 44 45 if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT | 46 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE | 47 RS_ALLOCATION_USAGE_GRAPHICS_VERTEX | 48 RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS | 49 RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET | 50 RS_ALLOCATION_USAGE_IO_INPUT | 51 RS_ALLOCATION_USAGE_IO_OUTPUT | 52 RS_ALLOCATION_USAGE_OEM | 53 RS_ALLOCATION_USAGE_SHARED)) != 0) { 54 ALOGE("Unknown usage specified."); 55 } 56 57 if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) { 58 mWriteAllowed = false; 59 if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT | 60 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE | 61 RS_ALLOCATION_USAGE_SCRIPT)) != 0) { 62 ALOGE("Invalid usage combination."); 63 } 64 } 65 66 mType = t; 67 mUsage = usage; 68 mAutoPadding = false; 69 if (t != nullptr) { 70 updateCacheInfo(t); 71 } 72 73 } 74 75 76 void Allocation::validateIsInt64() { 77 RsDataType dt = mType->getElement()->getDataType(); 78 if ((dt == RS_TYPE_SIGNED_64) || (dt == RS_TYPE_UNSIGNED_64)) { 79 return; 80 } 81 ALOGE("64 bit integer source does not match allocation type %i", dt); 82 } 83 84 void Allocation::validateIsInt32() { 85 RsDataType dt = mType->getElement()->getDataType(); 86 if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) { 87 return; 88 } 89 ALOGE("32 bit integer source does not match allocation type %i", dt); 90 } 91 92 void Allocation::validateIsInt16() { 93 RsDataType dt = mType->getElement()->getDataType(); 94 if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) { 95 return; 96 } 97 ALOGE("16 bit integer source does not match allocation type %i", dt); 98 } 99 100 void Allocation::validateIsInt8() { 101 RsDataType dt = mType->getElement()->getDataType(); 102 if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) { 103 return; 104 } 105 ALOGE("8 bit integer source does not match allocation type %i", dt); 106 } 107 108 void Allocation::validateIsFloat32() { 109 RsDataType dt = mType->getElement()->getDataType(); 110 if (dt == RS_TYPE_FLOAT_32) { 111 return; 112 } 113 ALOGE("32 bit float source does not match allocation type %i", dt); 114 } 115 116 void Allocation::validateIsFloat64() { 117 RsDataType dt = mType->getElement()->getDataType(); 118 if (dt == RS_TYPE_FLOAT_64) { 119 return; 120 } 121 ALOGE("64 bit float source does not match allocation type %i", dt); 122 } 123 124 void Allocation::validateIsObject() { 125 RsDataType dt = mType->getElement()->getDataType(); 126 if ((dt == RS_TYPE_ELEMENT) || 127 (dt == RS_TYPE_TYPE) || 128 (dt == RS_TYPE_ALLOCATION) || 129 (dt == RS_TYPE_SAMPLER) || 130 (dt == RS_TYPE_SCRIPT) || 131 (dt == RS_TYPE_MESH) || 132 (dt == RS_TYPE_PROGRAM_FRAGMENT) || 133 (dt == RS_TYPE_PROGRAM_VERTEX) || 134 (dt == RS_TYPE_PROGRAM_RASTER) || 135 (dt == RS_TYPE_PROGRAM_STORE)) { 136 return; 137 } 138 ALOGE("Object source does not match allocation type %i", dt); 139 } 140 141 void Allocation::updateFromNative() { 142 BaseObj::updateFromNative(); 143 144 const void *typeID = RS::dispatch->AllocationGetType(mRS->getContext(), getID()); 145 if(typeID != nullptr) { 146 sp<Type> t = new Type((void *)typeID, mRS); 147 t->updateFromNative(); 148 updateCacheInfo(t); 149 mType = t; 150 } 151 } 152 153 void Allocation::syncAll(RsAllocationUsageType srcLocation) { 154 switch (srcLocation) { 155 case RS_ALLOCATION_USAGE_SCRIPT: 156 case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS: 157 case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE: 158 case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX: 159 case RS_ALLOCATION_USAGE_SHARED: 160 break; 161 default: 162 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Source must be exactly one usage type."); 163 return; 164 } 165 tryDispatch(mRS, RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation)); 166 } 167 168 void * Allocation::getPointer(size_t *stride) { 169 void *p = nullptr; 170 if (!(mUsage & RS_ALLOCATION_USAGE_SHARED)) { 171 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Allocation does not support USAGE_SHARED."); 172 return nullptr; 173 } 174 175 // FIXME: decide if lack of getPointer should cause compat mode 176 if (RS::dispatch->AllocationGetPointer == nullptr) { 177 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Can't use getPointer on older APIs"); 178 return nullptr; 179 } 180 181 p = RS::dispatch->AllocationGetPointer(mRS->getContext(), getIDSafe(), 0, 182 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0, stride, sizeof(size_t)); 183 if (mRS->getError() != RS_SUCCESS) { 184 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation lock failed"); 185 p = nullptr; 186 } 187 return p; 188 } 189 190 // --------------------------------------------------------------------------- 191 //Functions needed for autopadding & unpadding 192 static void copyWithPadding(void* ptr, const void* srcPtr, int mSize, int count) { 193 int sizeBytesPad = mSize * 4; 194 int sizeBytes = mSize * 3; 195 uint8_t *dst = static_cast<uint8_t *>(ptr); 196 const uint8_t *src = static_cast<const uint8_t *>(srcPtr); 197 for (int i = 0; i < count; i++) { 198 memcpy(dst, src, sizeBytes); 199 dst += sizeBytesPad; 200 src += sizeBytes; 201 } 202 } 203 204 static void copyWithUnPadding(void* ptr, const void* srcPtr, int mSize, int count) { 205 int sizeBytesPad = mSize * 4; 206 int sizeBytes = mSize * 3; 207 uint8_t *dst = static_cast<uint8_t *>(ptr); 208 const uint8_t *src = static_cast<const uint8_t *>(srcPtr); 209 for (int i = 0; i < count; i++) { 210 memcpy(dst, src, sizeBytes); 211 dst += sizeBytes; 212 src += sizeBytesPad; 213 } 214 } 215 // --------------------------------------------------------------------------- 216 217 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) { 218 219 if(count < 1) { 220 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); 221 return; 222 } 223 if((off + count) > mCurrentCount) { 224 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off); 225 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); 226 return; 227 } 228 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { 229 size_t eSize = mType->getElement()->getSizeBytes(); 230 void *ptr = malloc(eSize * count); 231 copyWithPadding(ptr, data, eSize / 4, count); 232 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 233 count, ptr, count * mType->getElement()->getSizeBytes())); 234 free(ptr); 235 } else { 236 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 237 count, data, count * mType->getElement()->getSizeBytes())); 238 } 239 } 240 241 void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) { 242 if(count < 1) { 243 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); 244 return; 245 } 246 if((off + count) > mCurrentCount) { 247 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off); 248 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); 249 return; 250 } 251 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { 252 size_t eSize = mType->getElement()->getSizeBytes(); 253 void *ptr = malloc(eSize * count); 254 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 255 count, ptr, count * mType->getElement()->getSizeBytes())); 256 copyWithUnPadding(data, ptr, eSize / 4, count); 257 free(ptr); 258 } else { 259 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 260 count, data, count * mType->getElement()->getSizeBytes())); 261 } 262 } 263 264 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data, 265 uint32_t dataOff) { 266 267 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0, 268 mSelectedLOD, mSelectedFace, 269 count, 1, data->getIDSafe(), dataOff, 0, 270 data->mSelectedLOD, data->mSelectedFace)); 271 } 272 273 void Allocation::copy1DFrom(const void* data) { 274 copy1DRangeFrom(0, mCurrentCount, data); 275 } 276 277 void Allocation::copy1DTo(void* data) { 278 copy1DRangeTo(0, mCurrentCount, data); 279 } 280 281 282 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) { 283 if (mAdaptedAllocation != nullptr) { 284 285 } else { 286 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 287 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation."); 288 } 289 } 290 } 291 292 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 293 const void *data) { 294 validate2DRange(xoff, yoff, w, h); 295 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { 296 size_t eSize = mType->getElement()->getSizeBytes(); 297 void *ptr = malloc(eSize * w * h); 298 copyWithPadding(ptr, data, eSize / 4, w * h); 299 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, 300 yoff, mSelectedLOD, mSelectedFace, 301 w, h, ptr, w * h * mType->getElement()->getSizeBytes(), 302 w * mType->getElement()->getSizeBytes())); 303 free(ptr); 304 } else { 305 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, 306 yoff, mSelectedLOD, mSelectedFace, 307 w, h, data, w * h * mType->getElement()->getSizeBytes(), 308 w * mType->getElement()->getSizeBytes())); 309 } 310 } 311 312 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 313 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) { 314 validate2DRange(xoff, yoff, w, h); 315 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, 316 mSelectedLOD, mSelectedFace, 317 w, h, data->getIDSafe(), dataXoff, dataYoff, 318 data->mSelectedLOD, data->mSelectedFace)); 319 } 320 321 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 322 void* data) { 323 validate2DRange(xoff, yoff, w, h); 324 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { 325 size_t eSize = mType->getElement()->getSizeBytes(); 326 void *ptr = malloc(eSize * w * h); 327 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, 328 mSelectedLOD, mSelectedFace, w, h, ptr, 329 w * h * mType->getElement()->getSizeBytes(), 330 w * mType->getElement()->getSizeBytes())); 331 copyWithUnPadding(data, ptr, eSize / 4, w * h); 332 free(ptr); 333 } else { 334 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, 335 mSelectedLOD, mSelectedFace, w, h, data, 336 w * h * mType->getElement()->getSizeBytes(), 337 w * mType->getElement()->getSizeBytes())); 338 } 339 } 340 341 void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 342 const void *data, size_t stride) { 343 validate2DRange(xoff, yoff, w, h); 344 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, 345 mSelectedLOD, mSelectedFace, w, h, data, 346 w * h * mType->getElement()->getSizeBytes(), stride)); 347 } 348 349 void Allocation::copy2DStridedFrom(const void* data, size_t stride) { 350 copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 351 } 352 353 void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 354 void *data, size_t stride) { 355 validate2DRange(xoff, yoff, w, h); 356 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, 357 mSelectedLOD, mSelectedFace, w, h, data, 358 w * h * mType->getElement()->getSizeBytes(), stride)); 359 } 360 361 void Allocation::copy2DStridedTo(void* data, size_t stride) { 362 copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 363 } 364 365 void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, 366 uint32_t h, uint32_t d) { 367 if (mAdaptedAllocation != nullptr) { 368 369 } else { 370 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) { 371 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation."); 372 } 373 } 374 } 375 376 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, 377 uint32_t h, uint32_t d, const void* data) { 378 validate3DRange(xoff, yoff, zoff, w, h, d); 379 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { 380 size_t eSize = mType->getElement()->getSizeBytes(); 381 void *ptr = malloc(eSize * w * h * d); 382 copyWithPadding(ptr, data, eSize / 4, w * h * d); 383 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 384 mSelectedLOD, w, h, d, ptr, 385 w * h * d * mType->getElement()->getSizeBytes(), 386 w * mType->getElement()->getSizeBytes())); 387 free(ptr); 388 } else { 389 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 390 mSelectedLOD, w, h, d, data, 391 w * h * d * mType->getElement()->getSizeBytes(), 392 w * mType->getElement()->getSizeBytes())); 393 } 394 } 395 396 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d, 397 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) { 398 validate3DRange(xoff, yoff, zoff, w, h, d); 399 tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 400 mSelectedLOD, w, h, d, data->getIDSafe(), 401 dataXoff, dataYoff, dataZoff, data->mSelectedLOD)); 402 } 403 404 void Allocation::copy3DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, 405 uint32_t h, uint32_t d, void* data) { 406 validate3DRange(xoff, yoff, zoff, w, h, d); 407 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) { 408 size_t eSize = mType->getElement()->getSizeBytes(); 409 void *ptr = malloc(eSize * w * h * d); 410 tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 411 mSelectedLOD, w, h, d, ptr, 412 w * h * d * mType->getElement()->getSizeBytes(), 413 w * mType->getElement()->getSizeBytes())); 414 copyWithUnPadding(data, ptr, eSize / 4, w * h * d); 415 free(ptr); 416 } else { 417 tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 418 mSelectedLOD, w, h, d, data, 419 w * h * d * mType->getElement()->getSizeBytes(), 420 w * mType->getElement()->getSizeBytes())); 421 } 422 } 423 424 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 425 RsAllocationMipmapControl mipmaps, uint32_t usage) { 426 void *id = 0; 427 if (rs->getError() == RS_SUCCESS) { 428 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 0); 429 } 430 if (id == 0) { 431 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); 432 return nullptr; 433 } 434 return new Allocation(id, rs, type, usage); 435 } 436 437 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 438 RsAllocationMipmapControl mipmaps, uint32_t usage, 439 void *pointer) { 440 void *id = 0; 441 if (rs->getError() == RS_SUCCESS) { 442 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 443 (uintptr_t)pointer); 444 } 445 if (id == 0) { 446 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); 447 return nullptr; 448 } 449 return new Allocation(id, rs, type, usage); 450 } 451 452 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 453 uint32_t usage) { 454 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage); 455 } 456 457 sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e, 458 size_t count, uint32_t usage) { 459 Type::Builder b(rs, e); 460 b.setX(count); 461 sp<const Type> t = b.create(); 462 463 return createTyped(rs, t, usage); 464 } 465 466 sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e, 467 size_t x, size_t y, uint32_t usage) { 468 Type::Builder b(rs, e); 469 b.setX(x); 470 b.setY(y); 471 sp<const Type> t = b.create(); 472 473 return createTyped(rs, t, usage); 474 } 475 476 void Allocation::ioSendOutput() { 477 #ifndef RS_COMPATIBILITY_LIB 478 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) { 479 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified."); 480 return; 481 } 482 tryDispatch(mRS, RS::dispatch->AllocationIoSend(mRS->getContext(), getID())); 483 #endif 484 } 485 486 void Allocation::ioGetInput() { 487 #ifndef RS_COMPATIBILITY_LIB 488 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) { 489 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get buffer if IO_INPUT usage specified."); 490 return; 491 } 492 tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID())); 493 #endif 494 } 495 496 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB) 497 #include <gui/Surface.h> 498 499 RSC::sp<Surface> Allocation::getSurface() { 500 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) { 501 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get Surface if IO_INPUT usage specified."); 502 return nullptr; 503 } 504 IGraphicBufferProducer *v = (IGraphicBufferProducer *)RS::dispatch->AllocationGetSurface(mRS->getContext(), 505 getID()); 506 android::sp<IGraphicBufferProducer> bp = v; 507 v->decStrong(nullptr); 508 509 return new Surface(bp, true);; 510 } 511 512 void Allocation::setSurface(RSC::sp<Surface> s) { 513 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) { 514 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only set Surface if IO_OUTPUT usage specified."); 515 return; 516 } 517 tryDispatch(mRS, RS::dispatch->AllocationSetSurface(mRS->getContext(), getID(), 518 static_cast<ANativeWindow *>(s.get()))); 519 } 520 521 #endif 522 523