int IOMXHWBuffer_Setup( void *window, int w, int h, int hal_format, int hw_usage ) { ANativeWindow *anw = (ANativeWindow *)window; int usage = 0; status_t err; CHECK_ANW(); LOGD( "IOMXHWBuffer_setup: %p, %d, %d, %X, %X\n", anw, w, h, hal_format, hw_usage ); usage |= hw_usage | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; #if ANDROID_API >= 11 usage |= GRALLOC_USAGE_EXTERNAL_DISP; #endif err = native_window_set_usage( anw, usage ); CHECK_ERR(); #if ANDROID_API <= 13 err = native_window_set_buffers_geometry( anw, w, h, hal_format ); CHECK_ERR(); #else err = native_window_set_scaling_mode( anw, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW ); CHECK_ERR(); err = native_window_set_buffers_dimensions( anw, w, h ); CHECK_ERR(); err = native_window_set_buffers_format( anw, hal_format ); CHECK_ERR(); #endif return 0; }
explicit TestWindowData(SkISize size) : mSize(size) { android::BufferQueue::createBufferQueue(&mProducer, &mConsumer); mCpuConsumer = new android::CpuConsumer(mConsumer, 1); mCpuConsumer->setName(android::String8("TestWindowContext")); mCpuConsumer->setDefaultBufferSize(mSize.width(), mSize.height()); mAndroidSurface = new android::Surface(mProducer); native_window_set_buffers_dimensions(mAndroidSurface.get(), mSize.width(), mSize.height()); native_window_set_buffers_format(mAndroidSurface.get(), android::PIXEL_FORMAT_RGBA_8888); native_window_set_usage(mAndroidSurface.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_RENDER); mRootNode.reset(new android::uirenderer::RenderNode()); mRootNode->incStrong(nullptr); mRootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, mSize.width(), mSize.height()); mRootNode->mutateStagingProperties().setClipToBounds(false); mRootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC); ContextFactory factory; mProxy.reset(new android::uirenderer::renderthread::RenderProxy(false, mRootNode.get(), &factory)); mProxy->loadSystemProperties(); mProxy->initialize(mAndroidSurface.get()); float lightX = mSize.width() / 2.0f; android::uirenderer::Vector3 lightVector{lightX, -200.0f, 800.0f}; mProxy->setup(800.0f, 255 * 0.075f, 255 * 0.15f); mProxy->setLightCenter(lightVector); mCanvas.reset(new android::uirenderer::RecordingCanvas(mSize.width(), mSize.height())); }
SurfaceTextureClient* CanvasTexture::nativeWindow() { android::Mutex::Autolock lock(m_surfaceLock); if (m_ANW.get()) return m_ANW.get(); if (!m_texture) return 0; if (!useSurfaceTexture()) return 0; m_surfaceTexture = new android::SurfaceTexture(m_texture, false); m_ANW = new android::SurfaceTextureClient(m_surfaceTexture); int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888); GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result); if (result == NO_ERROR) { result = native_window_set_buffers_dimensions(m_ANW.get(), m_size.width(), m_size.height()); GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); } if (result != NO_ERROR) { m_useHwAcceleration = false; destroySurfaceTextureLocked(); return 0; } return m_ANW.get(); }
void WaylandNativeWindow::resize_callback(struct wl_egl_window *egl_window, void *) { TRACE("%dx%d",egl_window->width,egl_window->height); native_window_set_buffers_dimensions( (WaylandNativeWindow*)egl_window->nativewindow, egl_window->width,egl_window->height); }
bool EncodeInputSurface::init(const char* inputFileName, uint32_t fourcc, int width, int height) { m_width = width; m_height = height; int surfaceWidth = width; int surfaceHeight = height; static sp<SurfaceComposerClient> client = new SurfaceComposerClient(); //create surface static sp<SurfaceControl> surfaceCtl = client->createSurface(String8("testsurface"), surfaceWidth, surfaceHeight, HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL, 0); DEBUG("create surface with size %dx%d, format: 0x%x", surfaceWidth, surfaceHeight, HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL); // configure surface SurfaceComposerClient::openGlobalTransaction(); surfaceCtl->setLayer(100000); surfaceCtl->setPosition(100, 100); surfaceCtl->setSize(surfaceWidth, surfaceHeight); SurfaceComposerClient::closeGlobalTransaction(); m_surface = surfaceCtl->getSurface(); mNativeWindow = m_surface; int bufWidth = width; int bufHeight = height; int ret; INFO("set buffers geometry %dx%d\n", width, height); ret = native_window_set_buffers_dimensions(GET_ANATIVEWINDOW(mNativeWindow), width, height); CHECK_RET(ret, "native_window_set_buffers_dimensions"); uint32_t format = HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL; INFO("set buffers format %x\n", format); ret = native_window_set_buffers_format(GET_ANATIVEWINDOW(mNativeWindow), format); CHECK_RET(ret, "native_window_set_buffers_format"); INFO("set buffer usage\n"); ret = native_window_set_usage(GET_ANATIVEWINDOW(mNativeWindow), GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_HW_TEXTURE); CHECK_RET(ret, "native_window_set_usage"); INFO("set buffer count %d\n", m_bufferCount); ret = native_window_set_buffer_count(GET_ANATIVEWINDOW(mNativeWindow), m_bufferCount); CHECK_RET(ret, "native_window_set_buffer_count"); prepareInputBuffer(); return true; }
status_t BufferProducerThread::readyToRun() { sp<ANativeWindow> anw(mSurface); status_t err = native_window_set_usage(anw.get(), mStream.buffer_producer.usage); if (err != NO_ERROR) { return err; } err = native_window_set_buffers_dimensions( anw.get(), mStream.buffer_producer.width, mStream.buffer_producer.height); if (err != NO_ERROR) { return err; } err = native_window_set_buffers_format(anw.get(), mStream.buffer_producer.format); if (err != NO_ERROR) { return err; } return NO_ERROR; }
void CanvasTexture::setSize(const IntSize& size) { android::Mutex::Autolock lock(m_surfaceLock); if (m_size == size) return; m_size = size; if (m_ANW.get()) { if (useSurfaceTexture()) { int result = native_window_set_buffers_dimensions(m_ANW.get(), m_size.width(), m_size.height()); GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result); if (result != NO_ERROR) m_useHwAcceleration = false; // On error, drop out of HWA } if (!useSurfaceTexture()) destroySurfaceTextureLocked(); } }
Error HWUISink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const { // Do all setup in this function because we don't know the size // for the RenderNode and RenderProxy during the constructor. // In practice this doesn't seem too expensive. const SkISize size = src.size(); // Based on android::SurfaceTexture_init() android::sp<android::IGraphicBufferProducer> producer; android::sp<android::IGraphicBufferConsumer> consumer; android::BufferQueue::createBufferQueue(&producer, &consumer); // Consumer setup android::sp<android::CpuConsumer> cpuConsumer = new android::CpuConsumer(consumer, 1); cpuConsumer->setName(android::String8("SkiaTestClient")); cpuConsumer->setDefaultBufferSize(size.width(), size.height()); // Producer setup android::sp<android::Surface> surface = new android::Surface(producer); native_window_set_buffers_dimensions(surface.get(), size.width(), size.height()); native_window_set_buffers_format(surface.get(), android::PIXEL_FORMAT_RGBA_8888); native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_RENDER); // RenderNode setup based on hwui/tests/main.cpp:TreeContentAnimation SkAutoTDelete<android::uirenderer::RenderNode> rootNode (new android::uirenderer::RenderNode()); rootNode->incStrong(nullptr); // Values set here won't be applied until the framework has called // RenderNode::pushStagingPropertiesChanges() during RenderProxy::syncAndDrawFrame(). rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, size.width(), size.height()); rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::X | android::uirenderer::RenderNode::Y); rootNode->mutateStagingProperties().setClipToBounds(false); rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC); // RenderProxy setup based on hwui/tests/main.cpp:TreeContentAnimation ContextFactory factory; SkAutoTDelete<android::uirenderer::renderthread::RenderProxy> proxy (new android::uirenderer::renderthread::RenderProxy(false, rootNode, &factory)); proxy->loadSystemProperties(); proxy->initialize(surface.get()); float lightX = size.width() / 2.0f; android::uirenderer::Vector3 lightVector { lightX, dp(-200.0f), dp(800.0f) }; proxy->setup(size.width(), size.height(), lightVector, dp(800.0f), 255 * 0.075f, 255 * 0.15f, kDensity); // Do the draw SkAutoTDelete<android::uirenderer::DisplayListRenderer> renderer (new android::uirenderer::DisplayListRenderer()); renderer->setViewport(size.width(), size.height()); renderer->prepare(); renderer->clipRect(0, 0, size.width(), size.height(), SkRegion::Op::kReplace_Op); Error err = src.draw(renderer->asSkCanvas()); if (!err.isEmpty()) { return err; } renderer->finish(); rootNode->setStagingDisplayList(renderer->finishRecording()); proxy->syncAndDrawFrame(); proxy->fence(); // Capture pixels SkImageInfo destinationConfig = SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType); dst->allocPixels(destinationConfig); sk_memset32((uint32_t*) dst->getPixels(), SK_ColorRED, size.width() * size.height()); android::CpuConsumer::LockedBuffer nativeBuffer; android::status_t retval = cpuConsumer->lockNextBuffer(&nativeBuffer); if (retval == android::BAD_VALUE) { SkDebugf("HWUISink::draw() got no buffer; returning transparent"); // No buffer ready to read - commonly triggered by dm sending us // a no-op source, or calling code that doesn't do anything on this // backend. dst->eraseColor(SK_ColorTRANSPARENT); return ""; } else if (retval) { return SkStringPrintf("Failed to lock buffer to read pixels: %d.", retval); } // Move the pixels into the destination SkBitmap SK_ALWAYSBREAK(nativeBuffer.format == android::PIXEL_FORMAT_RGBA_8888 && "Native buffer not RGBA!"); SkImageInfo nativeConfig = SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height, kRGBA_8888_SkColorType, kPremul_SkAlphaType); // Android stride is in pixels, Skia stride is in bytes SkBitmap nativeWrapper; bool success = nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4); if (!success) { return "Failed to wrap HWUI buffer in a SkBitmap"; } SK_ALWAYSBREAK(dst->colorType() == kRGBA_8888_SkColorType && "Destination buffer not RGBA!"); success = nativeWrapper.readPixels(destinationConfig, dst->getPixels(), dst->rowBytes(), 0, 0); if (!success) { return "Failed to extract pixels from HWUI buffer"; } cpuConsumer->unlockBuffer(nativeBuffer); return ""; }
void SurfaceUtils::setBuffersDimensions(int w, int h) { native_window_set_buffers_dimensions(mWindow, w, h); }
void SoftwareRenderer::resetFormatIfChanged(const sp<AMessage> &format) { CHECK(format != NULL); int32_t colorFormatNew; CHECK(format->findInt32("color-format", &colorFormatNew)); int32_t widthNew, heightNew; CHECK(format->findInt32("stride", &widthNew)); CHECK(format->findInt32("slice-height", &heightNew)); int32_t cropLeftNew, cropTopNew, cropRightNew, cropBottomNew; if (!format->findRect( "crop", &cropLeftNew, &cropTopNew, &cropRightNew, &cropBottomNew)) { cropLeftNew = cropTopNew = 0; cropRightNew = widthNew - 1; cropBottomNew = heightNew - 1; } if (static_cast<int32_t>(mColorFormat) == colorFormatNew && mWidth == widthNew && mHeight == heightNew && mCropLeft == cropLeftNew && mCropTop == cropTopNew && mCropRight == cropRightNew && mCropBottom == cropBottomNew) { // Nothing changed, no need to reset renderer. return; } mColorFormat = static_cast<OMX_COLOR_FORMATTYPE>(colorFormatNew); mWidth = widthNew; mHeight = heightNew; mCropLeft = cropLeftNew; mCropTop = cropTopNew; mCropRight = cropRightNew; mCropBottom = cropBottomNew; mCropWidth = mCropRight - mCropLeft + 1; mCropHeight = mCropBottom - mCropTop + 1; int halFormat; size_t bufWidth, bufHeight; switch (mColorFormat) { case OMX_COLOR_FormatYUV420Planar: case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: case OMX_COLOR_FormatYUV420SemiPlanar: { if (!runningInEmulator()) { halFormat = HAL_PIXEL_FORMAT_YV12; bufWidth = (mCropWidth + 1) & ~1; bufHeight = (mCropHeight + 1) & ~1; break; } // fall through. } default: halFormat = HAL_PIXEL_FORMAT_RGB_565; bufWidth = mCropWidth; bufHeight = mCropHeight; mConverter = new ColorConverter( mColorFormat, OMX_COLOR_Format16bitRGB565); CHECK(mConverter->isValid()); break; } CHECK(mNativeWindow != NULL); CHECK(mCropWidth > 0); CHECK(mCropHeight > 0); CHECK(mConverter == NULL || mConverter->isValid()); CHECK_EQ(0, native_window_set_usage( mNativeWindow.get(), GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP)); CHECK_EQ(0, native_window_set_scaling_mode( mNativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)); // Width must be multiple of 32??? CHECK_EQ(0, native_window_set_buffers_dimensions( mNativeWindow.get(), bufWidth, bufHeight)); CHECK_EQ(0, native_window_set_buffers_format( mNativeWindow.get(), halFormat)); // NOTE: native window uses extended right-bottom coordinate android_native_rect_t crop; crop.left = mCropLeft; crop.top = mCropTop; crop.right = mCropRight + 1; crop.bottom = mCropBottom + 1; ALOGV("setting crop: [%d, %d, %d, %d] for size [%zu, %zu]", crop.left, crop.top, crop.right, crop.bottom, bufWidth, bufHeight); CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop)); int32_t rotationDegrees; if (!format->findInt32("rotation-degrees", &rotationDegrees)) { rotationDegrees = 0; } uint32_t transform; switch (rotationDegrees) { case 0: transform = 0; break; case 90: transform = HAL_TRANSFORM_ROT_90; break; case 180: transform = HAL_TRANSFORM_ROT_180; break; case 270: transform = HAL_TRANSFORM_ROT_270; break; default: transform = 0; break; } CHECK_EQ(0, native_window_set_buffers_transform( mNativeWindow.get(), transform)); }
status_t setNativeWindowSizeFormatAndUsage( ANativeWindow *nativeWindow /* nonnull */, int width, int height, int format, int rotation, int usage) { status_t err = native_window_set_buffers_dimensions(nativeWindow, width, height); if (err != NO_ERROR) { ALOGE("native_window_set_buffers_dimensions failed: %s (%d)", strerror(-err), -err); return err; } err = native_window_set_buffers_format(nativeWindow, format); if (err != NO_ERROR) { ALOGE("native_window_set_buffers_format failed: %s (%d)", strerror(-err), -err); return err; } int transform = 0; if ((rotation % 90) == 0) { switch ((rotation / 90) & 3) { case 1: transform = HAL_TRANSFORM_ROT_90; break; case 2: transform = HAL_TRANSFORM_ROT_180; break; case 3: transform = HAL_TRANSFORM_ROT_270; break; default: transform = 0; break; } } err = native_window_set_buffers_transform(nativeWindow, transform); if (err != NO_ERROR) { ALOGE("native_window_set_buffers_transform failed: %s (%d)", strerror(-err), -err); return err; } // Make sure to check whether either Stagefright or the video decoder // requested protected buffers. if (usage & GRALLOC_USAGE_PROTECTED) { // Verify that the ANativeWindow sends images directly to // SurfaceFlinger. int queuesToNativeWindow = 0; err = nativeWindow->query( nativeWindow, NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, &queuesToNativeWindow); if (err != NO_ERROR) { ALOGE("error authenticating native window: %s (%d)", strerror(-err), -err); return err; } if (queuesToNativeWindow != 1) { ALOGE("native window could not be authenticated"); return PERMISSION_DENIED; } } int consumerUsage = 0; err = nativeWindow->query(nativeWindow, NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage); if (err != NO_ERROR) { ALOGW("failed to get consumer usage bits. ignoring"); err = NO_ERROR; } int finalUsage = usage | consumerUsage; ALOGV("gralloc usage: %#x(producer) + %#x(consumer) = %#x", usage, consumerUsage, finalUsage); err = native_window_set_usage(nativeWindow, finalUsage); if (err != NO_ERROR) { ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err); return err; } err = native_window_set_scaling_mode( nativeWindow, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (err != NO_ERROR) { ALOGE("native_window_set_scaling_mode failed: %s (%d)", strerror(-err), -err); return err; } ALOGD("set up nativeWindow %p for %dx%d, color %#x, rotation %d, usage %#x", nativeWindow, width, height, format, rotation, finalUsage); return NO_ERROR; }
// This test is intended to verify that proper synchronization is done when // rendering into an FBO. TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { const int texWidth = 64; const int texHeight = 64; ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU)); ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(), texWidth, texHeight)); ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), HAL_PIXEL_FORMAT_RGBA_8888)); ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); android_native_buffer_t* anb; ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); ASSERT_TRUE(anb != NULL); sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); // Fill the buffer with green uint8_t* img = NULL; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255, 0, 255); buf->unlock(); ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1)); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); glBindFramebuffer(GL_FRAMEBUFFER, mFbo); drawTexture(); glBindFramebuffer(GL_FRAMEBUFFER, 0); for (int i = 0; i < 4; i++) { SCOPED_TRACE(String8::format("frame %d", i).string()); ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); ASSERT_TRUE(anb != NULL); buf = GraphicBuffer::from(anb); // Fill the buffer with red ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img))); fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0, 0, 255); ASSERT_EQ(NO_ERROR, buf->unlock()); ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1)); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); drawTexture(); EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255)); } glBindFramebuffer(GL_FRAMEBUFFER, mFbo); EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255)); }
status_t Camera3OutputStream::configureQueueLocked() { status_t res; mTraceFirstBuffer = true; if ((res = Camera3IOStreamBase::configureQueueLocked()) != OK) { return res; } ALOG_ASSERT(mConsumer != 0, "mConsumer should never be NULL"); // Configure consumer-side ANativeWindow interface res = native_window_api_connect(mConsumer.get(), NATIVE_WINDOW_API_CAMERA); if (res != OK) { ALOGE("%s: Unable to connect to native window for stream %d", __FUNCTION__, mId); return res; } res = native_window_set_usage(mConsumer.get(), camera3_stream::usage); if (res != OK) { ALOGE("%s: Unable to configure usage %08x for stream %d", __FUNCTION__, camera3_stream::usage, mId); return res; } res = native_window_set_scaling_mode(mConsumer.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (res != OK) { ALOGE("%s: Unable to configure stream scaling: %s (%d)", __FUNCTION__, strerror(-res), res); return res; } if (mMaxSize == 0) { // For buffers of known size res = native_window_set_buffers_dimensions(mConsumer.get(), camera3_stream::width, camera3_stream::height); } else { // For buffers with bounded size res = native_window_set_buffers_dimensions(mConsumer.get(), mMaxSize, 1); } if (res != OK) { ALOGE("%s: Unable to configure stream buffer dimensions" " %d x %d (maxSize %zu) for stream %d", __FUNCTION__, camera3_stream::width, camera3_stream::height, mMaxSize, mId); return res; } res = native_window_set_buffers_format(mConsumer.get(), camera3_stream::format); if (res != OK) { ALOGE("%s: Unable to configure stream buffer format %#x for stream %d", __FUNCTION__, camera3_stream::format, mId); return res; } int maxConsumerBuffers; res = mConsumer->query(mConsumer.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); if (res != OK) { ALOGE("%s: Unable to query consumer undequeued" " buffer count for stream %d", __FUNCTION__, mId); return res; } ALOGV("%s: Consumer wants %d buffers, HAL wants %d", __FUNCTION__, maxConsumerBuffers, camera3_stream::max_buffers); if (camera3_stream::max_buffers == 0) { ALOGE("%s: Camera HAL requested max_buffer count: %d, requires at least 1", __FUNCTION__, camera3_stream::max_buffers); return INVALID_OPERATION; } mTotalBufferCount = maxConsumerBuffers + camera3_stream::max_buffers; mHandoutTotalBufferCount = 0; mFrameCount = 0; mLastTimestamp = 0; res = native_window_set_buffer_count(mConsumer.get(), mTotalBufferCount); if (res != OK) { ALOGE("%s: Unable to set buffer count for stream %d", __FUNCTION__, mId); return res; } res = native_window_set_buffers_transform(mConsumer.get(), mTransform); if (res != OK) { ALOGE("%s: Unable to configure stream transform to %x: %s (%d)", __FUNCTION__, mTransform, strerror(-res), res); } return OK; }
void FakeSurfaceComposer::captureScreenImp(const sp<IGraphicBufferProducer>& producer, uint32_t reqWidth, uint32_t reqHeight, const sp<GraphicProducerWrapper>& wrapper) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(wrapper.get()); RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen(); // get screen geometry nsIntRect screenBounds = screen->GetNaturalBounds().ToUnknownRect(); const uint32_t hw_w = screenBounds.width; const uint32_t hw_h = screenBounds.height; if (reqWidth > hw_w || reqHeight > hw_h) { ALOGE("size mismatch (%d, %d) > (%d, %d)", reqWidth, reqHeight, hw_w, hw_h); static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE); return; } reqWidth = (!reqWidth) ? hw_w : reqWidth; reqHeight = (!reqHeight) ? hw_h : reqHeight; nsScreenGonk* screenPtr = screen.forget().take(); nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([screenPtr, reqWidth, reqHeight, producer, wrapper]() { // create a surface (because we're a producer, and we need to // dequeue/queue a buffer) sp<Surface> sur = new Surface(producer); ANativeWindow* window = sur.get(); if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != NO_ERROR) { static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(BAD_VALUE); NS_ReleaseOnMainThread(screenPtr); return; } uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; int err = 0; err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight); err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); err |= native_window_set_usage(window, usage); status_t result = NO_ERROR; if (err == NO_ERROR) { ANativeWindowBuffer* buffer; result = native_window_dequeue_buffer_and_wait(window, &buffer); if (result == NO_ERROR) { nsresult rv = screenPtr->MakeSnapshot(buffer); if (rv != NS_OK) { result = INVALID_OPERATION; } window->queueBuffer(window, buffer, -1); } } else { result = BAD_VALUE; } native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result); NS_ReleaseOnMainThread(screenPtr); }); mozilla::layers::CompositorParent::CompositorLoop()->PostTask( FROM_HERE, new RunnableCallTask(runnable)); }
bool_e anativewindow_allocate(anativewindow_t *anw, uint32_t buffer_width, uint32_t buffer_height, int32_t numBuffers, int32_t format, bool flipH) { if (format != ANW_NV12_FORMAT) return false_e; if (anw) { status_t status = 0; anw->m_format = format; anw->m_usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_SW_READ_OFTEN | // Non-cached ? If you use RARELY it will complain GRALLOC_USAGE_SW_WRITE_NEVER; // can't access from UVA anw->m_numBuffers = numBuffers; anw->m_width = buffer_width; anw->m_height = buffer_height; anw->m_native_buffers = (ANativeWindowBuffer **)calloc(numBuffers, sizeof(ANativeWindowBuffer *)); DVP_PRINT(DVP_ZONE_VIDEO, "Created %u pointers in native array %p\n", numBuffers, anw->m_native_buffers); if (anw->m_native_buffers == NULL) { return false_e; } // connect to the native window API status = native_window_api_connect(anw->m_window.get(), NATIVE_WINDOW_API_CAMERA); ANW_ERROR(status,"CONNECT"); // set the scaling mode of the windows status = native_window_set_scaling_mode(anw->m_window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); ANW_ERROR(status,"SCALING"); #if defined(BLAZE_TABLET) && defined(ICS) // set the layout of the buffer status = native_window_set_buffers_layout(anw->m_window.get(), NATIVE_WINDOW_BUFFERS_LAYOUT_PROGRESSIVE); // progressive ANW_ERROR(status,"LAYOUT"); #endif // set the format of the buffer status = native_window_set_buffers_format(anw->m_window.get(), anw->m_format); ANW_ERROR(status,"FORMAT"); // setup the dimensions status = native_window_set_buffers_dimensions(anw->m_window.get(), anw->m_width, anw->m_height); ANW_ERROR(status,"DIM"); if (flipH) { // set the horizontal flip status = native_window_set_buffers_transform(anw->m_window.get(), NATIVE_WINDOW_TRANSFORM_FLIP_H); ANW_ERROR(status,"TRANSFORM FLIP HORIZONTAL"); } // set the usage of the GRALLOC buffers status = native_window_set_usage(anw->m_window.get(), anw->m_usage); if (status < 0 ) { DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] USAGE status = %d (0x%08x)\n", __FUNCTION__, __LINE__, status, anw->m_usage); } // set the number of buffers required. status = native_window_set_buffer_count(anw->m_window.get(), anw->m_numBuffers); ANW_ERROR(status,"COUNT"); // get the number of dequeueable buffers status = anw->m_window->query(anw->m_window.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, (int*)&anw->m_nonqueue); ANW_ERROR(status,"QUERY NONQUEUE"); for (uint32_t n = 0; n < anw->m_numBuffers; n++) { status = anw->m_window->dequeueBuffer(anw->m_window.get(), &anw->m_native_buffers[n]); if (status != 0) { DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %s status = %d\n", __FUNCTION__, __LINE__, "Failed window buffer dequeue!", status); \ return false_e; } if (anw->m_native_buffers[n]) { native_handle_t *hdl = (native_handle_t *)anw->m_native_buffers[n]->handle; hdl = hdl; // warnings DVP_PRINT(DVP_ZONE_VIDEO, "ANativeBuffer %p => dim %dx%d stride %d usage %d format %d handle %p numFds=%u\n", anw->m_native_buffers[n], anw->m_native_buffers[n]->width, anw->m_native_buffers[n]->height, anw->m_native_buffers[n]->stride, anw->m_native_buffers[n]->usage, anw->m_native_buffers[n]->format, anw->m_native_buffers[n]->handle, hdl->numFds); } } return true_e; } return false_e; }