int PreviewRenderer::init() { int err = 0; ANativeWindow* anw = mSurface.get(); err = native_window_api_connect(anw, NATIVE_WINDOW_API_CPU); if (err) goto fail; err = native_window_set_usage( anw, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN); if (err) goto fail; err = native_window_set_buffer_count(anw, 3); if (err) goto fail; err = native_window_set_scaling_mode( anw, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (err) goto fail; err = native_window_set_buffers_geometry( anw, mWidth, mHeight, HAL_PIXEL_FORMAT_YV12); if (err) goto fail; err = native_window_set_buffers_transform(anw, 0); if (err) goto fail; fail: return err; }
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; }
void TransferQueue::initGLResources(int width, int height) { android::Mutex::Autolock lock(m_transferQueueItemLocks); if (!m_sharedSurfaceTextureId) { glGenTextures(1, &m_sharedSurfaceTextureId); sp<BufferQueue> bufferQueue(new BufferQueue(true)); m_sharedSurfaceTexture = #if GPU_UPLOAD_WITHOUT_DRAW new android::SurfaceTexture(m_sharedSurfaceTextureId, true, GL_TEXTURE_2D, true, bufferQueue); #else new android::SurfaceTexture(m_sharedSurfaceTextureId, true, GL_TEXTURE_EXTERNAL_OES, true, bufferQueue); #endif m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture); m_sharedSurfaceTexture->setSynchronousMode(true); int extraBuffersNeeded = 0; m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &extraBuffersNeeded); bufferQueue->setBufferCount(m_transferQueueSize + extraBuffersNeeded); int result = native_window_set_buffers_geometry(m_ANW.get(), width, height, HAL_PIXEL_FORMAT_RGBA_8888); GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result); result = native_window_set_usage(m_ANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); GLUtils::checkSurfaceTextureError("native_window_set_usage", result); } if (!m_fboID) glGenFramebuffers(1, &m_fboID); }
void TransferQueue::initSharedSurfaceTextures(int width, int height) { if (!m_sharedSurfaceTextureId) { glGenTextures(1, &m_sharedSurfaceTextureId); m_sharedSurfaceTexture = #if GPU_UPLOAD_WITHOUT_DRAW new android::SurfaceTexture(m_sharedSurfaceTextureId, true, GL_TEXTURE_2D); #else new android::SurfaceTexture(m_sharedSurfaceTextureId); #endif m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture); m_sharedSurfaceTexture->setSynchronousMode(true); m_sharedSurfaceTexture->setBufferCount(ST_BUFFER_NUMBER+1); int result = native_window_set_buffers_geometry(m_ANW.get(), width, height, HAL_PIXEL_FORMAT_RGBA_8888); GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result); result = native_window_set_usage(m_ANW.get(), GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); GLUtils::checkSurfaceTextureError("native_window_set_usage", result); } if (!m_fboID) glGenFramebuffers(1, &m_fboID); }
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())); }
void NativeWindowRenderer::queueExternalBuffer(ANativeWindow* anw, MediaBuffer* buffer, int width, int height) { native_window_set_buffers_geometry(anw, width, height, HAL_PIXEL_FORMAT_YV12); native_window_set_usage(anw, GRALLOC_USAGE_SW_WRITE_OFTEN); #ifdef QCOM_HARDWARE native_window_set_buffer_count(anw, 3); #endif ANativeWindowBuffer* anb; anw->dequeueBuffer(anw, &anb); CHECK(anb != NULL); sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); CHECK(NO_ERROR == anw->lockBuffer(anw, buf->getNativeBuffer())); // Copy the buffer uint8_t* img = NULL; buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); copyI420Buffer(buffer, img, width, height, buf->getStride()); #if PREVIEW_DEBUG FILE *fp1 = fopen("/sdcard/pre_test_yuv.raw", "ab"); if(fp1 == NULL) LOGE("Errors file can not be created"); else { fwrite(img, buf->getWidth() * buf->getHeight()* 3/2, 1, fp1); fclose(fp1); } #endif buf->unlock(); CHECK(NO_ERROR == anw->queueBuffer(anw, buf->getNativeBuffer())); }
// 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_set_buffers_geometry(mANW.get(), texWidth, texHeight, 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(new GraphicBuffer(anb, false)); // 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 = new GraphicBuffer(anb, false); // 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)); }
CedarXSoftwareRenderer::CedarXSoftwareRenderer( const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) : mYUVMode(None), mNativeWindow(nativeWindow) { int32_t tmp; CHECK(meta->findInt32(kKeyColorFormat, &tmp)); mColorFormat = (OMX_COLOR_FORMATTYPE)tmp; //CHECK(meta->findInt32(kKeyScreenID, &screenID)); //CHECK(meta->findInt32(kKeyColorFormat, &halFormat)); CHECK(meta->findInt32(kKeyWidth, &mWidth)); CHECK(meta->findInt32(kKeyHeight, &mHeight)); int32_t rotationDegrees; if (!meta->findInt32(kKeyRotation, &rotationDegrees)) { rotationDegrees = 0; } int halFormat; size_t bufWidth, bufHeight; halFormat = HAL_PIXEL_FORMAT_YV12; bufWidth = mWidth; bufHeight = mHeight; CHECK(mNativeWindow != NULL); 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_geometry( mNativeWindow.get(), bufWidth, bufHeight, halFormat)); 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; } if (transform) { CHECK_EQ(0, native_window_set_buffers_transform( mNativeWindow.get(), transform)); } }
FrameBufferAndroid::FrameBufferAndroid(ANativeWindow* window, int width, int height) : FrameBuffer(width, height, false, false), nativeWindow(window), buffer(nullptr), gralloc(nullptr) { hw_module_t const* pModule; hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); gralloc = reinterpret_cast<gralloc_module_t const*>(pModule); nativeWindow->common.incRef(&nativeWindow->common); native_window_set_usage(nativeWindow, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); }
// This test probably doesn't belong here. TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp<ANativeWindow> anw(mSurface); // Verify the screenshot works with no protected buffers. sp<CpuConsumer> consumer = new CpuConsumer(1); sp<ISurfaceComposer> sf(ComposerService::getComposerService()); sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); ASSERT_EQ(NO_ERROR, sf->captureScreen(display, consumer->getBufferQueue(), 64, 64, 0, 0x7fffffff, true)); // Set the PROTECTED usage bit and verify that the screenshot fails. Note // that we need to dequeue a buffer in order for it to actually get // allocated in SurfaceFlinger. ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), GRALLOC_USAGE_PROTECTED)); ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); ANativeWindowBuffer* buf = 0; status_t err = native_window_dequeue_buffer_and_wait(anw.get(), &buf); if (err) { // we could fail if GRALLOC_USAGE_PROTECTED is not supported. // that's okay as long as this is the reason for the failure. // try again without the GRALLOC_USAGE_PROTECTED bit. ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0)); ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), &buf)); return; } ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf, -1)); for (int i = 0; i < 4; i++) { // Loop to make sure SurfaceFlinger has retired a protected buffer. ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), &buf)); ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1)); } ASSERT_EQ(NO_ERROR, sf->captureScreen(display, consumer->getBufferQueue(), 64, 64, 0, 0x7fffffff, true)); }
static struct native_surface * android_display_create_window_surface(struct native_display *ndpy, EGLNativeWindowType win, const struct native_config *nconf) { struct android_display *adpy = android_display(ndpy); struct android_config *aconf = android_config(nconf); struct android_surface *asurf; enum pipe_format format; int val; if (win->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { LOGE("invalid native window with magic 0x%x", win->common.magic); return NULL; } if (win->query(win, NATIVE_WINDOW_FORMAT, &val)) { LOGE("failed to query native window format"); return NULL; } format = get_pipe_format(val); if (format != nconf->color_format) { LOGW("native window format 0x%x != config format 0x%x", format, nconf->color_format); if (!adpy->base.screen->is_format_supported(adpy->base.screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { LOGE("and the native window cannot be used as a render target"); return NULL; } } asurf = CALLOC_STRUCT(android_surface); if (!asurf) return NULL; asurf->adpy = adpy; asurf->win = win; asurf->win->common.incRef(&asurf->win->common); /* request buffers that are for CPU access */ if (!adpy->use_drm) { native_window_set_usage(asurf->win, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); } asurf->base.destroy = android_surface_destroy; asurf->base.present = android_surface_present; asurf->base.validate = android_surface_validate; asurf->base.wait = android_surface_wait; return &asurf->base; }
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 NativeWindowRenderer::queueExternalBuffer(ANativeWindow* anw, MediaBuffer* buffer, int width, int height) { native_window_set_buffers_geometry(anw, width, height, HAL_PIXEL_FORMAT_YV12); native_window_set_usage(anw, GRALLOC_USAGE_SW_WRITE_OFTEN); ANativeWindowBuffer* anb; CHECK(NO_ERROR == native_window_dequeue_buffer_and_wait(anw, &anb)); CHECK(anb != NULL); // Copy the buffer uint8_t* img = NULL; sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); copyI420Buffer(buffer, img, width, height, buf->getStride()); buf->unlock(); CHECK(NO_ERROR == anw->queueBuffer(anw, buf->getNativeBuffer(), -1)); }
bool createNativeWindow(__u32 pixelformat) { mClient = new SurfaceComposerClient(); mSurfaceCtl = mClient->createSurface(String8("testsurface"), 800, 600, pixelformat, 0); // configure surface SurfaceComposerClient::openGlobalTransaction(); mSurfaceCtl->setLayer(100000); mSurfaceCtl->setPosition(100, 100); mSurfaceCtl->setSize(800, 600); SurfaceComposerClient::closeGlobalTransaction(); mSurface = mSurfaceCtl->getSurface(); mNativeWindow = mSurface; int bufWidth = 640; int bufHeight = 480; 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)); CHECK_EQ(0, native_window_set_buffers_geometry( mNativeWindow.get(), bufWidth, bufHeight, pixelformat)); return true; }
SoftwareRenderer::SoftwareRenderer( const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) : mConverter(NULL), mYUVMode(None), mNativeWindow(nativeWindow) { int32_t tmp; CHECK(meta->findInt32(kKeyColorFormat, &tmp)); mColorFormat = (OMX_COLOR_FORMATTYPE)tmp; CHECK(meta->findInt32(kKeyWidth, &mWidth)); CHECK(meta->findInt32(kKeyHeight, &mHeight)); if (!meta->findRect( kKeyCropRect, &mCropLeft, &mCropTop, &mCropRight, &mCropBottom)) { mCropLeft = mCropTop = 0; mCropRight = mWidth - 1; mCropBottom = mHeight - 1; } mCropWidth = mCropRight - mCropLeft + 1; mCropHeight = mCropBottom - mCropTop + 1; int32_t rotationDegrees; if (!meta->findInt32(kKeyRotation, &rotationDegrees)) { rotationDegrees = 0; } int halFormat; size_t bufWidth, bufHeight; switch (mColorFormat) { case OMX_COLOR_FormatYUV420Planar: case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: { halFormat = HAL_PIXEL_FORMAT_YV12; bufWidth = (mCropWidth + 1) & ~1; bufHeight = (mCropHeight + 1) & ~1; if (ALIGN(bufWidth, 16) / 2 == ALIGN(bufWidth / 2, 16)) { break; } } 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_geometry( mNativeWindow.get(), bufWidth, bufHeight, halFormat)); 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; } if (transform) { CHECK_EQ(0, native_window_set_buffers_transform( mNativeWindow.get(), transform)); } }
status_t StreamAdapter::connectToDevice(camera2_device_t *d, uint32_t width, uint32_t height, int format) { if (mState != UNINITIALIZED) return INVALID_OPERATION; if (d == NULL) { ALOGE("%s: Null device passed to stream adapter", __FUNCTION__); return BAD_VALUE; } status_t res; mWidth = width; mHeight = height; mFormat = format; // Allocate device-side stream interface uint32_t id; uint32_t formatActual; // ignored uint32_t usage; uint32_t maxBuffers = 2; res = d->ops->allocate_stream(d, mWidth, mHeight, mFormat, getStreamOps(), &id, &formatActual, &usage, &maxBuffers); if (res != OK) { ALOGE("%s: Device stream allocation failed: %s (%d)", __FUNCTION__, strerror(-res), res); mState = UNINITIALIZED; return res; } mDevice = d; mId = id; mUsage = usage; mMaxProducerBuffers = maxBuffers; // Configure consumer-side ANativeWindow interface res = native_window_api_connect(mConsumerInterface.get(), NATIVE_WINDOW_API_CAMERA); if (res != OK) { ALOGE("%s: Unable to connect to native window for stream %d", __FUNCTION__, mId); mState = ALLOCATED; return res; } res = native_window_set_usage(mConsumerInterface.get(), mUsage); if (res != OK) { ALOGE("%s: Unable to configure usage %08x for stream %d", __FUNCTION__, mUsage, mId); mState = CONNECTED; return res; } res = native_window_set_buffers_geometry(mConsumerInterface.get(), mWidth, mHeight, mFormat); if (res != OK) { ALOGE("%s: Unable to configure buffer geometry" " %d x %d, format 0x%x for stream %d", __FUNCTION__, mWidth, mHeight, mFormat, mId); mState = CONNECTED; return res; } int maxConsumerBuffers; res = mConsumerInterface->query(mConsumerInterface.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers); if (res != OK) { ALOGE("%s: Unable to query consumer undequeued" " buffer count for stream %d", __FUNCTION__, mId); mState = CONNECTED; return res; } mMaxConsumerBuffers = maxConsumerBuffers; ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__, mMaxProducerBuffers, mMaxConsumerBuffers); int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers; res = native_window_set_buffer_count(mConsumerInterface.get(), totalBuffers); if (res != OK) { ALOGE("%s: Unable to set buffer count for stream %d", __FUNCTION__, mId); mState = CONNECTED; return res; } // Register allocated buffers with HAL device buffer_handle_t *buffers = new buffer_handle_t[totalBuffers]; ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers]; int bufferIdx = 0; for (; bufferIdx < totalBuffers; bufferIdx++) { res = native_window_dequeue_buffer_and_wait(mConsumerInterface.get(), &anwBuffers[bufferIdx]); if (res != OK) { ALOGE("%s: Unable to dequeue buffer %d for initial registration for" "stream %d", __FUNCTION__, bufferIdx, mId); mState = CONNECTED; goto cleanUpBuffers; } buffers[bufferIdx] = anwBuffers[bufferIdx]->handle; } res = mDevice->ops->register_stream_buffers(mDevice, mId, totalBuffers, buffers); if (res != OK) { ALOGE("%s: Unable to register buffers with HAL device for stream %d", __FUNCTION__, mId); mState = CONNECTED; } else { mState = ACTIVE; } cleanUpBuffers: for (int i = 0; i < bufferIdx; i++) { res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(), anwBuffers[i], -1); } delete anwBuffers; delete buffers; return res; }
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::setUsage(int usage) { native_window_set_usage(mWindow, usage); }
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)); }
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)); }
CedarXSoftwareRenderer::CedarXSoftwareRenderer( const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) : mYUVMode(None), mNativeWindow(nativeWindow) { int32_t tmp; CHECK(meta->findInt32(kKeyColorFormat, &tmp)); //mColorFormat = (OMX_COLOR_FORMATTYPE)tmp; //CHECK(meta->findInt32(kKeyScreenID, &screenID)); //CHECK(meta->findInt32(kKeyColorFormat, &halFormat)); CHECK(meta->findInt32(kKeyWidth, &mWidth)); CHECK(meta->findInt32(kKeyHeight, &mHeight)); int32_t nVdecInitRotation; //clock wise. int32_t rotationDegrees; //anti-clock wise, if (!meta->findInt32(kKeyRotation, &nVdecInitRotation)) { LOGD("(f:%s, l:%d) find fail nVdecInitRotation[%d]", __FUNCTION__, __LINE__, nVdecInitRotation); rotationDegrees = 0; } else { switch(nVdecInitRotation) { case 0: { rotationDegrees = 0; break; } case 1: { rotationDegrees = 270; break; } case 2: { rotationDegrees = 180; break; } case 3: { rotationDegrees = 90; break; } default: { LOGW("(f:%s, l:%d) nInitRotation=%d", __FUNCTION__, __LINE__, nVdecInitRotation); rotationDegrees = 0; break; } } } meta->findInt32(kKey3dDoubleStream, &m3dModeDoubleStreamFlag); int GpuBufHeight_num = 0; int halFormat; size_t bufWidth, bufHeight; size_t nGpuBufWidth, nGpuBufHeight; if(0 == m3dModeDoubleStreamFlag) { GpuBufHeight_num = 1; } else { LOGD("(f:%s, l:%d) be careful for 3d double stream!", __FUNCTION__, __LINE__); GpuBufHeight_num = 2; } halFormat = HAL_PIXEL_FORMAT_YV12; bufWidth = mWidth; bufHeight = mHeight; if(bufWidth != ((mWidth + 15) & ~15)) { LOGW("(f:%s, l:%d) bufWidth[%d]!=display_width[%d]", __FUNCTION__, __LINE__, ((mWidth + 15) & ~15), mWidth); } if(bufHeight != ((mHeight + 15) & ~15)) { LOGW("(f:%s, l:%d) bufHeight[%d]!=display_height[%d]", __FUNCTION__, __LINE__, ((mHeight + 15) & ~15), mHeight); } CHECK(mNativeWindow != NULL); int usage = 0; meta->findInt32(kKeyIsDRM, &usage); if(usage) { LOGV("protected video"); usage = GRALLOC_USAGE_PROTECTED; } usage |= GRALLOC_USAGE_SW_READ_NEVER /*| GRALLOC_USAGE_SW_WRITE_OFTEN*/ | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP; CHECK_EQ(0, native_window_set_usage( mNativeWindow.get(), usage)); CHECK_EQ(0, native_window_set_scaling_mode( mNativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)); // Width must be multiple of 32??? nGpuBufWidth = mWidth; nGpuBufHeight = mHeight; #if (defined(__CHIP_VERSION_F23) || (defined(__CHIP_VERSION_F51))) #if (1 == ADAPT_A10_GPU_RENDER) nGpuBufWidth = (mWidth + 15) & ~15; //A10's GPU has a bug, we can avoid it if(nGpuBufHeight%8 != 0) { LOGD("(f:%s, l:%d) original gpu buf align_width[%d], height[%d]mod8 = %d", __FUNCTION__, __LINE__, nGpuBufWidth, nGpuBufHeight, nGpuBufHeight%8); if((nGpuBufWidth*nGpuBufHeight)%256 != 0) { // e:\videofile\test_stream\avi, 800*450 LOGW("(f:%s, l:%d) original gpu buf align_width[%d]*height[%d]mod1024 = %d", __FUNCTION__, __LINE__, nGpuBufWidth, nGpuBufHeight, (nGpuBufWidth*nGpuBufHeight)%1024); nGpuBufHeight = (nGpuBufHeight+7)&~7; LOGW("(f:%s, l:%d) change gpu buf height to [%d]", __FUNCTION__, __LINE__, nGpuBufHeight); } } nGpuBufWidth = mWidth; //restore GpuBufWidth to mWidth; #endif #elif defined(__CHIP_VERSION_F33) #if (1 == ADAPT_A31_GPU_RENDER) //A31 GPU rect width should 8 align. if(mWidth%8 != 0) { nGpuBufWidth = (mWidth + 7) & ~7; LOGD("(f:%s, l:%d) A31 gpuBufWidth[%d]mod16=[%d] ,should 8 align, change to [%d]", __FUNCTION__, __LINE__, mWidth, mWidth%8, nGpuBufWidth); } #endif #else #error "Unknown chip type!" #endif CHECK_EQ(0, native_window_set_buffers_geometry( mNativeWindow.get(), //(bufWidth + 15) & ~15, //(bufHeight+ 15) & ~15, //(bufWidth + 15) & ~15, //bufHeight, //bufWidth, //bufHeight, nGpuBufWidth, nGpuBufHeight * GpuBufHeight_num, halFormat)); 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; } if (transform) { LOGD("(f:%s, l:%d) transform[%d]", __FUNCTION__, __LINE__, transform); CHECK_EQ(0, native_window_set_buffers_transform( mNativeWindow.get(), transform)); } Rect crop; crop.left = 0; crop.top = 0; crop.right = bufWidth; crop.bottom = bufHeight; mNativeWindow->perform(mNativeWindow.get(), NATIVE_WINDOW_SET_CROP, &crop); }
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; }
SoftwareRenderer::SoftwareRenderer( const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) : mConverter(NULL), mYUVMode(None), mNativeWindow(nativeWindow) { int32_t tmp; CHECK(meta->findInt32(kKeyColorFormat, &tmp)); mColorFormat = (OMX_COLOR_FORMATTYPE)tmp; CHECK(meta->findInt32(kKeyWidth, &mWidth)); CHECK(meta->findInt32(kKeyHeight, &mHeight)); if (!meta->findRect( kKeyCropRect, &mCropLeft, &mCropTop, &mCropRight, &mCropBottom)) { mCropLeft = mCropTop = 0; mCropRight = mWidth - 1; mCropBottom = mHeight - 1; } mCropWidth = mCropRight - mCropLeft + 1; mCropHeight = mCropBottom - mCropTop + 1; int32_t rotationDegrees; if (!meta->findInt32(kKeyRotation, &rotationDegrees)) { rotationDegrees = 0; } int halFormat; size_t bufWidth, bufHeight; switch (mColorFormat) { case OMX_COLOR_FormatYUV420Planar: case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: { if (!runningInEmulator()) { halFormat = HAL_PIXEL_FORMAT_YV12; bufWidth = (mCropWidth + 1) & ~1; bufHeight = (mCropHeight + 1) & ~1; break; } // fall through. } #ifdef QCOM_LEGACY_OMX case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: { halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; bufWidth = (mCropWidth + 1) & ~1; bufHeight = (mCropHeight + 1) & ~1; mAlign = ((mWidth + 15) & -16) * ((mHeight + 15) & -16); break; } #endif default: halFormat = HAL_PIXEL_FORMAT_RGB_565; bufWidth = mCropWidth; bufHeight = mCropHeight; mConverter = new ColorConverter( mColorFormat, OMX_COLOR_Format16bitRGB565); CHECK(mConverter->isValid()); break; } ALOGI("Buffer color format: 0x%X", mColorFormat); ALOGI("Video params: mWidth: %d, mHeight: %d, mCropWidth: %d, mCropHeight: %d, mCropTop: %d, mCropLeft: %d", mWidth, mHeight, mCropWidth, mCropHeight, mCropTop, mCropLeft); CHECK(mNativeWindow != NULL); CHECK(mCropWidth > 0); CHECK(mCropHeight > 0); CHECK(mConverter == NULL || mConverter->isValid()); #ifdef EXYNOS4_ENHANCEMENTS 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 | GRALLOC_USAGE_HW_FIMC1 | GRALLOC_USAGE_HWC_HWOVERLAY)); #else 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 #ifdef QCOM_LEGACY_OMX | GRALLOC_USAGE_PRIVATE_ADSP_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED #endif )); #endif 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_geometry( mNativeWindow.get(), bufWidth, bufHeight, halFormat)); 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; } if (transform) { CHECK_EQ(0, native_window_set_buffers_transform( mNativeWindow.get(), transform)); } }
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; }
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; }