static void draw(void) { const VGint w = 48; VGImage img1, img2; VGint x, y; vgSetfv(VG_CLEAR_COLOR, 4, white); vgClear(0, 0, window_width(), window_height()); img1 = vgCreateImage(VG_sRGBA_8888, w, w, VG_IMAGE_QUALITY_NONANTIALIASED); img2 = vgCreateImage(VG_sRGBA_8888, w, w, VG_IMAGE_QUALITY_NONANTIALIASED); x = 5; y = (window_height() - w) / 2; /* test vgSetPixels */ vgSetfv(VG_CLEAR_COLOR, 4, red); vgClearImage(img1, 0, 0, w, w / 2); vgSetfv(VG_CLEAR_COLOR, 4, black); vgClearImage(img1, 0, w / 2, w, w / 2); vgSetPixels(x, y, img1, 0, 0, w, w); x += w + 5; /* test vgDrawImage */ vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); vgLoadIdentity(); vgTranslate(x, y); vgDrawImage(img1); /* test vgGetPixels */ vgGetPixels(img1, 0, 0, x, y, w, w); x += w + 5; vgSetPixels(x, y, img1, 0, 0, w, w); x += w + 5; /* test vgCopyImage */ vgCopyImage(img2, 0, 0, img1, 0, 0, w, w, VG_FALSE); vgSetPixels(x, y, img2, 0, 0, w, w); /* vgCopyPixels */ vgCopyPixels(x + w + 5, y, x, y, w, w); vgDestroyImage(img1); vgDestroyImage(img2); }
void TiledImageOpenVG::detachTiles() { makeSharedContextCurrent(); // because we create new images int numTiles = m_tiles.size(); VGImage newTile, originalTile; for (int i = 0; i < numTiles; ++i) { originalTile = m_tiles.at(i); if (originalTile == VG_INVALID_HANDLE) continue; VGImageFormat format = (VGImageFormat) vgGetParameteri(originalTile, VG_IMAGE_FORMAT); VGint width = vgGetParameteri(originalTile, VG_IMAGE_WIDTH); VGint height = vgGetParameteri(originalTile, VG_IMAGE_HEIGHT); ASSERT_VG_NO_ERROR(); newTile = vgCreateImage(format, width, height, VG_IMAGE_QUALITY_FASTER); ASSERT_VG_NO_ERROR(); vgCopyImage(newTile, 0, 0, originalTile, 0, 0, width, height, VG_FALSE /* dither */); ASSERT_VG_NO_ERROR(); m_tiles.at(i) = newTile; } }
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle) { bool ret = false; if (index >= MAX_EGLIMAGE_TEXTURES) { *image_handle = NULL; return false; } eglBindAPI(EGL_OPENVG_API); eglMakeCurrent(g_egl_dpy, g_pbuff_surf, g_pbuff_surf, g_eglimage_ctx); if (!eglBuffer[index] || !g_egl_vgimage[index]) { g_egl_vgimage[index] = vgCreateImage(rgb32 ? VG_sXRGB_8888 : VG_sRGB_565, g_egl_res, g_egl_res, VG_IMAGE_QUALITY_NONANTIALIASED); eglBuffer[index] = peglCreateImageKHR(g_egl_dpy, g_eglimage_ctx, EGL_VG_PARENT_IMAGE_KHR, (EGLClientBuffer)g_egl_vgimage[index], NULL); ret = true; } vgImageSubData(g_egl_vgimage[index], frame, pitch, (rgb32 ? VG_sXRGB_8888 : VG_sRGB_565), 0, 0, width, height); *image_handle = eglBuffer[index]; gfx_ctx_bind_api(g_api); eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx); return ret; }
// makeimage makes an image from a raw raster of red, green, blue, alpha values void makeimage(VGfloat x, VGfloat y, int w, int h, VGubyte * data) { unsigned int dstride = w * 4; VGImageFormat rgbaFormat = VG_sABGR_8888; VGImage img = vgCreateImage(rgbaFormat, w, h, VG_IMAGE_QUALITY_BETTER); vgImageSubData(img, (void *)data, dstride, rgbaFormat, 0, 0, w, h); vgSetPixels(x, y, img, 0, 0, w, h); vgDestroyImage(img); }
VGImage ResizeImage(VGImage src, int width, int height) { int orig_width = vgGetParameteri(src, VG_IMAGE_WIDTH); int orig_height = vgGetParameteri(src, VG_IMAGE_HEIGHT); printf("(%d, %d)\n", orig_width, orig_height); VGImage dst = vgCreateImage(VG_sABGR_8888, width, height, VG_IMAGE_QUALITY_BETTER); vgCopyImage(dst, 0, 0,src,0,0,width, height,0); return dst; }
NativeImagePtr RGBA32Buffer::asNewNativeImage() const { if (!m_image) { static const VGImageFormat bufferFormat = VG_sARGB_8888_PRE; // Save memory by using 16-bit images for fully opaque images. const VGImageFormat imageFormat = hasAlpha() ? WEBKIT_OPENVG_NATIVE_IMAGE_FORMAT_s_8888 : VG_sRGB_565; #if PLATFORM(EGL) EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent(); #endif const IntSize vgMaxImageSize(vgGeti(VG_MAX_IMAGE_WIDTH), vgGeti(VG_MAX_IMAGE_HEIGHT)); ASSERT_VG_NO_ERROR(); PassRefPtr<TiledImageOpenVG> tiledImage = adoptRef(new TiledImageOpenVG( IntSize(width(), height()), vgMaxImageSize)); const int numColumns = tiledImage->numColumns(); const int numRows = tiledImage->numRows(); for (int yIndex = 0; yIndex < numRows; ++yIndex) { for (int xIndex = 0; xIndex < numColumns; ++xIndex) { IntRect tileRect = tiledImage->tileRect(xIndex, yIndex); VGImage tile = vgCreateImage(imageFormat, tileRect.width(), tileRect.height(), VG_IMAGE_QUALITY_FASTER); ASSERT_VG_NO_ERROR(); PixelData* pixelData = m_bytes.data(); pixelData += (tileRect.y() * width()) + tileRect.x(); vgImageSubData(tile, reinterpret_cast<unsigned char*>(pixelData), width() * sizeof(PixelData), bufferFormat, 0, 0, tileRect.width(), tileRect.height()); ASSERT_VG_NO_ERROR(); tiledImage->setTile(xIndex, yIndex, tile); } } // Incomplete images will be returned without storing them in m_image, // so the image will be regenerated once loading is complete. if (m_status != FrameComplete) return tiledImage; m_image = tiledImage; m_bytes.clear(); } return m_image; // and increase refcount }
int render(int width, int height) { static DWORD startTick =0; static DWORD frames = 0; VGImage image; char buf[256]; if((startTick == 0)||(frames > 50)) { if(frames > 50) frames = 0; startTick = GetTickCount(); frames++; } else { sprintf(buf, "fps:%2.2f frames/sec \n", (float)(frames++)*1000/(GetTickCount() - startTick)); OutputDebugString(buf); } if(pReadFile == NULL) { pReadFile = fopen("test.rgb","rb"); if(pReadFile) fseek(pReadFile, 0 , SEEK_SET); } if(pReadFile && (feof(pReadFile))) fseek(pReadFile, 0 , SEEK_SET); if(pReadFile) fread(pBuff, sizeof(BYTE),SRC_WIDTH*SRC_HEIGHT*2,pReadFile); image = vgCreateImage( VG_sRGB_565, SRC_WIDTH, SRC_HEIGHT, VG_IMAGE_QUALITY_BETTER ); if(image == NULL) return -1; vgImageSubData( image, pBuff, SRC_WIDTH*2, VG_sRGB_565, 0, 0, SRC_WIDTH, SRC_HEIGHT); vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); vgLoadIdentity(); vgScale((VGfloat)width/SRC_WIDTH, (VGfloat)height/SRC_HEIGHT); vgTranslate(SRC_WIDTH, SRC_HEIGHT); vgRotate(180.0f); vgDrawImage( image ); vgDestroyImage( image ); if ( vgGetError() == VG_NO_ERROR ) eglSwapBuffers( egldisplay, eglsurface ); return 0; }
VGImage QVGImagePool::createPermanentImage(VGImageFormat format, VGint width, VGint height, VGbitfield allowedQuality) { VGImage image; do { image = vgCreateImage(format, width, height, allowedQuality); if (image != VG_INVALID_HANDLE) return image; } while (reclaimSpace(format, width, height, 0)); qWarning("QVGImagePool: cannot reclaim sufficient space for a %dx%d image", width, height); return VG_INVALID_HANDLE; }
static void draw(void) { VGint WINDSIZEX = window_width(); VGint WINDSIZEY = window_height(); VGPaint fill; VGPath box; VGfloat color[4] = {1.f, 0.f, 0.f, 1.f}; VGfloat bgCol[4] = {0.7f, 0.7f, 0.7f, 1.0f}; VGfloat transCol[4] = {0.f, 0.f, 0.f, 0.f}; VGImage image = vgCreateImage(VG_sRGBA_8888, img_width, img_height, VG_IMAGE_QUALITY_NONANTIALIASED); /* Background clear */ fill = vgCreatePaint(); vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color); vgSetPaint(fill, VG_FILL_PATH); box = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); /* Rectangle to cover completely 16x16 pixel area. */ RectToPath(box, 0, 0, 64, 64); vgSetfv(VG_CLEAR_COLOR, 4, transCol); vgClearImage(image, 0, 0, img_width, img_height); vgSetfv(VG_CLEAR_COLOR, 4, color); vgClearImage(image, 10, 10, 12, 12); //vgImageSubData(image, pukki_64x64_data, pukki_64x64_stride, // VG_sRGBA_8888, 0, 0, 32, 32); vgSeti(VG_MASKING, VG_TRUE); vgLoadIdentity(); vgSetfv(VG_CLEAR_COLOR, 4, bgCol); vgClear(0, 0, WINDSIZEX, WINDSIZEY); vgMask(image, VG_FILL_MASK, 0, 0, window_width(), window_height()); vgMask(image, VG_SET_MASK, x_pos, y_pos, 100, 100); vgDrawPath(box, VG_FILL_PATH); //vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); //vgTranslate(-10, -10); //vgDrawImage(image); vgDestroyPaint(fill); vgDestroyPath(box); }
VGImage QVGImagePool::createTemporaryImage(VGImageFormat format, VGint width, VGint height, VGbitfield allowedQuality, QVGPixmapData *keepData) { VGImage image; do { image = vgCreateImage(format, width, height, allowedQuality); if (image != VG_INVALID_HANDLE) return image; } while (reclaimSpace(format, width, height, keepData)); qWarning("QVGImagePool: cannot reclaim sufficient space for a %dx%d temporary image", width, height); return VG_INVALID_HANDLE; }
static void rpi_render_message(rpi_t *rpi, const char *msg) { free(rpi->mLastMsg); rpi->mLastMsg = strdup(msg); if (rpi->mMsgLength) { while (--rpi->mMsgLength) vgClearGlyph(rpi->mFont, rpi->mMsgLength); vgClearGlyph(rpi->mFont, 0); } struct font_output_list out; font_renderer_msg(rpi->mFontRenderer, msg, &out); struct font_output *head = out.head; while (head) { if (rpi->mMsgLength >= 1024) break; VGfloat origin[2], escapement[2]; VGImage img; escapement[0] = head->advance_x; escapement[1] = head->advance_y; origin[0] = -head->char_off_x; origin[1] = -head->char_off_y; img = vgCreateImage(VG_A_8, head->width, head->height, VG_IMAGE_QUALITY_NONANTIALIASED); // flip it for (unsigned i = 0; i < head->height; i++) vgImageSubData(img, head->output + head->pitch * i, head->pitch, VG_A_8, 0, head->height - i - 1, head->width, 1); vgSetGlyphToImage(rpi->mFont, rpi->mMsgLength, img, origin, escapement); vgDestroyImage(img); rpi->mMsgLength++; head = head->next; } font_renderer_free_output(&out); for (unsigned i = 0; i < rpi->mMsgLength; i++) rpi->mGlyphIndices[i] = i; }
static bool gfx_ctx_vc_image_buffer_write(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle) { bool ret = false; vc_ctx_data_t *vc = (vc_ctx_data_t*)data; if (!vc || index >= MAX_EGLIMAGE_TEXTURES) goto error; eglBindAPI(EGL_OPENVG_API); eglMakeCurrent(vc->egl.dpy, vc->pbuff_surf, vc->pbuff_surf, vc->eglimage_ctx); if (!vc->eglBuffer[index] || !vc->vgimage[index]) { vc->vgimage[index] = vgCreateImage( rgb32 ? VG_sXRGB_8888 : VG_sRGB_565, vc->res, vc->res, VG_IMAGE_QUALITY_NONANTIALIASED); vc->eglBuffer[index] = peglCreateImageKHR( vc->egl.dpy, vc->eglimage_ctx, EGL_VG_PARENT_IMAGE_KHR, (EGLClientBuffer)vc->vgimage[index], NULL); ret = true; } vgImageSubData( vc->vgimage[index], frame, pitch, (rgb32 ? VG_sXRGB_8888 : VG_sRGB_565), 0, 0, width, height); *image_handle = vc->eglBuffer[index]; gfx_ctx_vc_bind_api(NULL, vc_api, 0, 0); eglMakeCurrent(vc->egl.dpy, vc->egl.surf, vc->egl.surf, vc->egl.ctx); return ret; error: *image_handle = NULL; return false; }
VGImage createImageFromRaw(const char * filename) { FILE *fp = fopen(filename, "rb"); if (!fp) { printf("File %s not found.\n", filename); } VGubyte *sourceImage; long int imageSize; fseek(fp, 0L, SEEK_END); imageSize = ftell(fp); fseek(fp, 0L, SEEK_SET); sourceImage = (VGubyte *)malloc(imageSize-8); assert(sourceImage != NULL); int *dimensions; dimensions = (int*)malloc(8); long int nrDimensionElements = fread(dimensions, 4, 2, fp); assert(nrDimensionElements == 2); fseek(fp, 8L, SEEK_SET); long int nrbytes = fread(sourceImage, 1, imageSize-8, fp); assert(nrbytes == imageSize-8); int w = dimensions[0]; int h = dimensions[1]; printf("Reading raw image with dimensions %d x %d\n", w, h); unsigned int dstride = w * 4; VGImageFormat rgbaFormat = VG_sABGR_8888; VGImage img = vgCreateImage(rgbaFormat, w, h, VG_IMAGE_QUALITY_BETTER); vgImageSubData(img, (void *)sourceImage, dstride, rgbaFormat, 0, 0, w, h); fclose(fp); free(dimensions); free(sourceImage); return img; }
VGImage QVGImagePool::createImageForPixmap(VGImageFormat format, VGint width, VGint height, VGbitfield allowedQuality, QVGPixmapData *data) { VGImage image; do { image = vgCreateImage(format, width, height, allowedQuality); if (image != VG_INVALID_HANDLE) { if (data) moveToHeadOfLRU(data); return image; } } while (reclaimSpace(format, width, height, data)); qWarning("QVGImagePool: cannot reclaim sufficient space for a %dx%d pixmap", width, height); return VG_INVALID_HANDLE; }
VGImage QVGPixmapData::toVGImage(qreal opacity) { #if !defined(QT_SHIVAVG) // Force the primary VG image to be recreated if necessary. if (toVGImage() == VG_INVALID_HANDLE) return VG_INVALID_HANDLE; if (opacity == 1.0f) return vgImage; // Create an alternative image for the selected opacity. if (vgImageOpacity == VG_INVALID_HANDLE || cachedOpacity != opacity) { if (vgImageOpacity == VG_INVALID_HANDLE) { if (inImagePool) { vgImageOpacity = QVGImagePool::instance()->createImageForPixmap (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this); } else { vgImageOpacity = vgCreateImage (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); } // Bail out if we run out of GPU memory - try again next time. if (vgImageOpacity == VG_INVALID_HANDLE) return VG_INVALID_HANDLE; } VGfloat matrix[20] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, opacity, 0.0f, 0.0f, 0.0f, 0.0f }; vgColorMatrix(vgImageOpacity, vgImage, matrix); cachedOpacity = opacity; } return vgImageOpacity; #else // vgColorMatrix() doesn't work with ShivaVG, so ignore the opacity. Q_UNUSED(opacity); return toVGImage(); #endif }
int mouse_init(int screen_width, int screen_height) { mouse.max_x = screen_width; mouse.max_y = screen_height; // Allocate memory for restoring mouse covered pixels: cursorx = mouse.max_x / 2; cursory = mouse.max_y / 2; cbsize = (CUR_SIZ * 2) + 1; CursorBuffer = vgCreateImage(VG_sABGR_8888, cbsize, cbsize, VG_IMAGE_QUALITY_BETTER); // CREATE A THREAD TO READ FROM DEVICE: pthread_t inputThread; int result = pthread_create(&inputThread, NULL, &eventThread, NULL); if (result != 0) { fprintf(stderr, "Unable to initialize the mouse\n"); } return 0; }
void QVGEGLWindowSurfaceVGImage::beginPaint(QWidget *widget) { QEglContext *context = ensureContext(widget); if (context) { if (recreateBackBuffer || backBufferSurface == EGL_NO_SURFACE) { // Create a VGImage object to act as the back buffer // for this window. We have to create the VGImage with a // current context, so activate the main surface for the window. context->makeCurrent(mainSurface()); recreateBackBuffer = false; if (backBufferSurface != EGL_NO_SURFACE) { eglDestroySurface(QEgl::display(), backBufferSurface); backBufferSurface = EGL_NO_SURFACE; } if (backBuffer != VG_INVALID_HANDLE) { vgDestroyImage(backBuffer); } VGImageFormat format = qt_vg_config_to_vg_format(context); backBuffer = vgCreateImage (format, size.width(), size.height(), VG_IMAGE_QUALITY_FASTER); if (backBuffer != VG_INVALID_HANDLE) { // Create an EGL surface for rendering into the VGImage. backBufferSurface = eglCreatePbufferFromClientBuffer (QEgl::display(), EGL_OPENVG_IMAGE, (EGLClientBuffer)(backBuffer), context->config(), NULL); if (backBufferSurface == EGL_NO_SURFACE) { vgDestroyImage(backBuffer); backBuffer = VG_INVALID_HANDLE; } } } if (backBufferSurface != EGL_NO_SURFACE) context->makeCurrent(backBufferSurface); else context->makeCurrent(mainSurface()); isPaintingActive = true; } }
NativeImagePtr RGBA32Buffer::asNewNativeImage() const { static const VGImageFormat bufferFormat = VG_sARGB_8888_PRE; // Save memory by using 16-bit images for fully opaque images. const VGImageFormat imageFormat = hasAlpha() ? bufferFormat : VG_sRGB_565; #if PLATFORM(EGL) EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent(); #endif const IntSize vgMaxImageSize(vgGeti(VG_MAX_IMAGE_WIDTH), vgGeti(VG_MAX_IMAGE_HEIGHT)); ASSERT_VG_NO_ERROR(); TiledImageOpenVG* tiledImage = new TiledImageOpenVG(IntSize(width(), height()), vgMaxImageSize); const int numColumns = tiledImage->numColumns(); const int numRows = tiledImage->numRows(); for (int yIndex = 0; yIndex < numRows; ++yIndex) { for (int xIndex = 0; xIndex < numColumns; ++xIndex) { IntRect tileRect = tiledImage->tileRect(xIndex, yIndex); VGImage image = vgCreateImage(imageFormat, tileRect.width(), tileRect.height(), VG_IMAGE_QUALITY_FASTER); ASSERT_VG_NO_ERROR(); PixelData* pixelData = const_cast<PixelData*>(m_bytes); pixelData += (tileRect.y() * width()) + tileRect.x(); vgImageSubData(image, reinterpret_cast<unsigned char*>(pixelData), width() * sizeof(PixelData), bufferFormat, 0, 0, tileRect.width(), tileRect.height()); ASSERT_VG_NO_ERROR(); tiledImage->setTile(xIndex, yIndex, image); } } return tiledImage; }
int main() { int width, height, cursorx, cursory, cbsize; init(&width, &height); // Graphics initialization cursorx = width / 2; cursory = height / 2; cbsize = (CUR_SIZ * 2) + 1; VGImage CursorBuffer = vgCreateImage(VG_sABGR_8888, cbsize, cbsize, VG_IMAGE_QUALITY_BETTER); if (mouseinit(width, height) != 0) { fprintf(stderr, "Unable to initialize the mouse\n"); exit(1); } Start(width, height); // Start the picture Background(0, 0, 0); // Black background Fill(44, 77, 232, 1); // Big blue marble Circle(width / 2, 0, width); // The "world" Fill(255, 255, 255, 1); // White text TextMid(width / 2, height / 2, "hello, world", SerifTypeface, width / 10); // Greetings End(); // update picture // MAIN LOOP while (left_count < 2) { // Loop until the left mouse button pressed & released // if the mouse moved... if (mouse.x != cursorx || mouse.y != cursory) { restoreCursor(CursorBuffer); cursorx = mouse.x; cursory = mouse.y; saveCursor(CursorBuffer, cursorx, cursory, width, height, CUR_SIZ); circleCursor(cursorx, cursory, width, height, CUR_SIZ); End(); // update picture } } restoreCursor(CursorBuffer); // not strictly necessary as display will be closed vgDestroyImage(CursorBuffer); // tidy up memory finish(); // Graphics cleanup exit(0); }
int EGLUtilsVG::loadTexture(const char *fn) { char testr[256]; sprintf(testr, ":/%s", fn ); QString filename = QString( testr ); QImage image = QImage( filename ); int w=image.width(); int h=image.height(); qDebug() << filename << "w:" << w << "h:" << h; VGImage texture = vgCreateImage(VG_sARGB_8888, w, h, VG_IMAGE_QUALITY_BETTER); qDebug("vgCreateImage handle %x", texture); if(texture==VG_INVALID_HANDLE) { VGErrorCode err = vgGetError(); qDebug("loadVGImage '%s' error 0x%x", fn, err); } vgImageSubData(texture, (QRgb*)image.bits(), w*4, VG_sARGB_8888, 0, 0, w, h); return texture; }
ImageBufferData::ImageBufferData(const IntSize& size, int colorSpace, bool& success) : m_surface(0) { ASSERT(size.width() > 0); ASSERT(size.height() > 0); success = false; switch (colorSpace) { case ColorSpaceDeviceRGB: m_format = WEBKIT_OPENVG_NATIVE_IMAGE_FORMAT_s_8888; break; case ColorSpaceSRGB: m_format = VG_sL_8; break; case ColorSpaceLinearRGB: m_format = WEBKIT_OPENVG_NATIVE_IMAGE_FORMAT_l_8888; break; } const IntSize vgMaxImageSize(vgGeti(VG_MAX_IMAGE_WIDTH), vgGeti(VG_MAX_IMAGE_HEIGHT)); ASSERT_VG_NO_ERROR(); if (size.width() <= vgMaxImageSize.width() && size.height() <= vgMaxImageSize.height()) { VGImage image = vgCreateImage(m_format, size.width(), size.height(), VG_IMAGE_QUALITY_FASTER); if (image == VG_INVALID_HANDLE) { // Clear VG error so that subsequent assertions don't trigger. // We can fall back to pbuffer surfaces, so let's not error out. vgGetError(); } else { ASSERT_VG_NO_ERROR(); m_tiledImage = adoptRef(new TiledImageOpenVG(size, vgMaxImageSize)); m_tiledImage->setTile(0, 0, image); } } #if PLATFORM(EGL) EGLint errorCode; if (m_tiledImage) { m_surface = new SurfaceOpenVG( (EGLClientBuffer*) m_tiledImage->tile(0, 0), EGL_OPENVG_IMAGE, EGLDisplayOpenVG::current()->display(), 0, &errorCode); } else m_surface = new SurfaceOpenVG(size, EGLDisplayOpenVG::current()->display(), 0, &errorCode); #else ASSERT_NOT_REACHED(); return; #endif if (!m_surface->isValid()) { delete m_surface; m_surface = 0; m_tiledImage.clear(); return; } m_surface->makeCurrent(); // Clear the ImageBuffer from whatever color was set before to transparent. const VGfloat transparent[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; vgSeti(VG_SCISSORING, VG_FALSE); vgSetfv(VG_CLEAR_COLOR, 4, transparent); vgClear(0, 0, size.width(), size.height()); success = true; }
/** Overridden function, which creates Open VG images for foreground, background, shadow and outline components of the font. @param aGlyphImage Source bitmap data in 256 grey format. Each pixel value is an index to a constant lookup table. Four entries of this table represent % of Outline, Shadow, Fill and Background colour to be used to get the final colour to be displayed on screen. @param aGlyphImageSize Size of the glyph bitmap image. @param aForeground Foreground component of the glyph. @param aOutline Outline component of the glyph. @param aShadow Shadow component of the glyph. @param aPreAllocForeground Pre-allocated buffer which will be used for setting text foreground VG image @param aPreAllocOutline Pre-allocated buffer which will be used for setting text outline VG image @param aPreAllocShadow Pre-allocated buffer which will be used for setting text shadow VG image @post Requested OpenVG images are ready for rendering. */ void CFontGlyphTree::CreateVGImageL(const TUint8* aGlyphImage, const TSize& aGlyphImageSize, VGImage& aForeground, VGImage& aOutline, VGImage& aShadow, TUint8* aPreAllocForeground, TUint8* aPreAllocOutline, TUint8* aPreAllocShadow) { TInt dataStride = aGlyphImageSize.iWidth; TInt targetByteCount = dataStride * aGlyphImageSize.iHeight; // Allocate memory and transform source into target format. // TAny* foregroundBuffer = NULL; TAny* outlineBuffer = NULL; TAny* shadowBuffer = NULL; TBool destroyTempBuffer = EFalse; if(aPreAllocForeground && aPreAllocOutline && aPreAllocShadow && (aGlyphImageSize.iWidth <= KMaxSizeImageOOM.iWidth) && (aGlyphImageSize.iHeight <= KMaxSizeImageOOM.iHeight)) { foregroundBuffer = aPreAllocForeground; outlineBuffer = aPreAllocOutline; shadowBuffer = aPreAllocShadow; } else { foregroundBuffer = User::AllocL(targetByteCount); CleanupStack::PushL(foregroundBuffer); outlineBuffer = User::AllocL(targetByteCount); CleanupStack::PushL(outlineBuffer); shadowBuffer = User::AllocL(targetByteCount); CleanupStack::PushL(shadowBuffer); destroyTempBuffer = ETrue; } TUint8* foregroundByte = static_cast <TUint8*> (foregroundBuffer); TUint8* outlineByte = static_cast <TUint8*> (outlineBuffer); TUint8* shadowByte = static_cast <TUint8*> (shadowBuffer); const TUint8* endByte = (TUint8*)aGlyphImage + targetByteCount; TUint8* curSrcGlyphImage = const_cast <TUint8*> (aGlyphImage); while (curSrcGlyphImage < endByte) { *outlineByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KOutlineColorIndex]; *shadowByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KShadowColorIndex]; *foregroundByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KFillColorIndex]; curSrcGlyphImage++; } const VGImageFormat imageFormat = VG_sL_8; if(aForeground == VG_INVALID_HANDLE) { aForeground = vgCreateImage(imageFormat, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); if(aForeground == VG_INVALID_HANDLE) { User::Leave(KErrNoMemory); } aOutline = vgCreateImage(imageFormat, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); if(aOutline == VG_INVALID_HANDLE) { DestroyVGImage(&aForeground); User::Leave(KErrNoMemory); } aShadow = vgCreateImage(imageFormat, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); if(aShadow == VG_INVALID_HANDLE) { DestroyVGImage(&aForeground, &aOutline); User::Leave(KErrNoMemory); } } vgImageSubData( aForeground, foregroundBuffer, dataStride, imageFormat, 0, 0,aGlyphImageSize.iWidth, aGlyphImageSize.iHeight); #ifdef DRAWGLYPH_MULTIPLY_MODE VGImage image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); vgColorMatrix(image, aForeground, KColorMatrix); vgDestroyImage(aForeground); aForeground = image; #endif // DRAWGLYPH_MULTIPLY_MODE vgImageSubData( aOutline, outlineBuffer, dataStride, imageFormat, 0, 0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight); #ifdef DRAWGLYPH_MULTIPLY_MODE image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); vgColorMatrix(image, aOutline, KColorMatrix); vgDestroyImage(aOutline); aOutline = image; #endif // DRAWGLYPH_MULTIPLY_MODE vgImageSubData( aShadow, shadowBuffer, dataStride, imageFormat, 0, 0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight); #ifdef DRAWGLYPH_MULTIPLY_MODE image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); vgColorMatrix(image, aShadow, KColorMatrix); vgDestroyImage(aShadow); aShadow = image; #endif // DRAWGLYPH_MULTIPLY_MODE if(destroyTempBuffer) { CleanupStack::PopAndDestroy(3, foregroundBuffer); } }
static void *vg_init(const video_info_t *video, const input_driver_t **input, void **input_data) { unsigned temp_width = 0, temp_height = 0; VGfloat clearColor[4] = {0, 0, 0, 1}; settings_t *settings = config_get_ptr(); driver_t *driver = driver_get_ptr(); const gfx_ctx_driver_t *ctx = NULL; vg_t *vg = (vg_t*)calloc(1, sizeof(vg_t)); if (!vg) goto error; ctx = gfx_ctx_init_first(vg, settings->video.context_driver, GFX_CTX_OPENVG_API, 0, 0, false); if (!ctx) goto error; driver->video_context = ctx; gfx_ctx_get_video_size(vg, &temp_width, &temp_height); RARCH_LOG("Detecting screen resolution %ux%u.\n", temp_width, temp_height); if (temp_width != 0 && temp_height != 0) { video_driver_set_size_width(temp_width); video_driver_set_size_width(temp_height); } gfx_ctx_swap_interval(vg, video->vsync ? 1 : 0); gfx_ctx_update_window_title(vg); vg->mTexType = video->rgb32 ? VG_sXRGB_8888 : VG_sRGB_565; vg->keep_aspect = video->force_aspect; unsigned win_width = video->width; unsigned win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { video_driver_get_size(&temp_width, &temp_height); win_width = temp_width; win_height = temp_height; } if (!gfx_ctx_set_video_mode(vg, win_width, win_height, video->fullscreen)) goto error; video_driver_get_size(&temp_width, &temp_height); temp_width = 0; temp_height = 0; gfx_ctx_get_video_size(vg, &temp_width, &temp_height); vg->should_resize = true; if (temp_width != 0 && temp_height != 0) { RARCH_LOG("Verified window resolution %ux%u.\n", temp_width, temp_height); video_driver_set_size_width(temp_width); video_driver_set_size_height(temp_height); } video_driver_get_size(&temp_width, &temp_height); vg->mScreenAspect = (float)temp_width / temp_height; gfx_ctx_translate_aspect(vg, &vg->mScreenAspect, temp_width, temp_height); vgSetfv(VG_CLEAR_COLOR, 4, clearColor); vg->mTextureWidth = vg->mTextureHeight = video->input_scale * RARCH_SCALE_BASE; vg->mImage = vgCreateImage(vg->mTexType, vg->mTextureWidth, vg->mTextureHeight, video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED); vg_set_nonblock_state(vg, !video->vsync); gfx_ctx_input_driver(vg, input, input_data); if (settings->video.font_enable && font_renderer_create_default(&vg->font_driver, &vg->mFontRenderer, *settings->video.font_path ? settings->video.font_path : NULL, settings->video.font_size)) { vg->mFont = vgCreateFont(0); if (vg->mFont != VG_INVALID_HANDLE) { vg->mFontsOn = true; vg->mFontHeight = settings->video.font_size; vg->mPaintFg = vgCreatePaint(); vg->mPaintBg = vgCreatePaint(); VGfloat paintFg[] = { settings->video.msg_color_r, settings->video.msg_color_g, settings->video.msg_color_b, 1.0f }; VGfloat paintBg[] = { settings->video.msg_color_r / 2.0f, settings->video.msg_color_g / 2.0f, settings->video.msg_color_b / 2.0f, 0.5f }; vgSetParameteri(vg->mPaintFg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(vg->mPaintFg, VG_PAINT_COLOR, 4, paintFg); vgSetParameteri(vg->mPaintBg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(vg->mPaintBg, VG_PAINT_COLOR, 4, paintBg); } } if (vg_query_extension("KHR_EGL_image") && gfx_ctx_image_buffer_init(vg, video)) { pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)gfx_ctx_get_proc_address("vgCreateEGLImageTargetKHR"); if (pvgCreateEGLImageTargetKHR) { RARCH_LOG("[VG] Using EGLImage buffer\n"); vg->mEglImageBuf = true; } } #if 0 const char *ext = (const char*)vgGetString(VG_EXTENSIONS); if (ext) RARCH_LOG("[VG] Supported extensions: %s\n", ext); #endif return vg; error: if (vg) free(vg); if (driver) driver->video_context = NULL; return NULL; }
/** Overridden function, which creates OpenVG images for monochrome and anti-aliased fonts. @param aGlyphImage Data source bitmap in 256 or 2 Grey format. @param aGlyphImageSize Glyph image data size. @param aDisplayMode Image display mode. @param aForeground Foreground component of the glyph. @param aPreAllocForeground Pre-allocated buffer which will be used for setting foreground VG image @post Requested OpenVG image is ready for rendering. @panic Panic if bitmap display mode is not 256 grey or 2 grey. */ void CFontGlyphTree::CreateVGImageL(const TUint8* aGlyphImage, const TSize& aGlyphImageSize, TDisplayMode aDisplayMode, VGImage& aForeground, TUint8* aPreAllocForeground) { GRAPHICS_ASSERT_DEBUG((aDisplayMode == EGray256) || (aDisplayMode == EGray2), EDirectGdiPanicInvalidDisplayMode); GRAPHICS_ASSERT_DEBUG(aGlyphImage, EDirectGdiPanicInvalidParameter); VGImageFormat imageFormat = VG_IMAGE_FORMAT_INVALID; TInt vgCompatibleSourceStride = 0x00; TUint32 binaryDataArray[32]; TUint8* binaryData = NULL; TUint8* tempBuffer = NULL; if(aDisplayMode == EGray256) { imageFormat = VG_sL_8; vgCompatibleSourceStride = aGlyphImageSize.iWidth; binaryData = const_cast <TUint8*> (aGlyphImage); } else //EGray2 { imageFormat = VG_BW_1; vgCompatibleSourceStride = ((aGlyphImageSize.iWidth + 31) / 32) << 2; if (aGlyphImageSize.iWidth > 30 || aGlyphImageSize.iHeight > 32) { binaryData = aPreAllocForeground; if(!binaryData) { tempBuffer = (TUint8*) User::AllocL(vgCompatibleSourceStride * aGlyphImageSize.iHeight); CleanupStack::PushL(tempBuffer); binaryData = tempBuffer; } DecodeBinaryDataExLarge(aGlyphImageSize, aGlyphImage, vgCompatibleSourceStride, reinterpret_cast <TUint32*> (binaryData)); } else { DecodeBinaryData(aGlyphImageSize, aGlyphImage, binaryDataArray); binaryData = reinterpret_cast <TUint8*> (binaryDataArray); } } if(aForeground == VG_INVALID_HANDLE) { aForeground = vgCreateImage(imageFormat, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); } if (aForeground != VG_INVALID_HANDLE) { // Copy from the source image to our new VGImage vgImageSubData(aForeground, binaryData, vgCompatibleSourceStride, imageFormat, 0, 0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight); #ifdef DRAWGLYPH_MULTIPLY_MODE VGImage image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED); vgColorMatrix(image, aForeground, KColorMatrix); vgDestroyImage(aForeground); aForeground = image; #endif } else { if(tempBuffer) { CleanupStack::PopAndDestroy(tempBuffer); } User::Leave(KErrNoMemory); } if(tempBuffer) { CleanupStack::PopAndDestroy(tempBuffer); } }
/******************************************************************************* * Function Name : InitView * Returns : true if no error occured * Description : Code in InitView() will be called by the Shell upon a change * in the rendering context. * Used to initialise variables that are dependent on the rendering * context (e.g. textures, vertex buffers, etc.) *******************************************************************************/ bool CImage::InitView() { //Create a pair of images m_avgImage[0] = vgCreateImage(VG_sRGBA_8888, IMG_SIZE, IMG_SIZE, VG_IMAGE_QUALITY_NONANTIALIASED); m_avgImage[1] = vgCreateImage(VG_sRGBA_8888, IMG_SIZE, IMG_SIZE, VG_IMAGE_QUALITY_NONANTIALIASED); /* The first image will be populated from memory. A 32bit integer array (8bits per component) is created and populated. */ VGuint* pui32ImgData = new VGuint[IMG_SIZE * IMG_SIZE]; for (int i = 0; i < IMG_SIZE; ++i) { for (int j = 0; j < IMG_SIZE; ++j) { // Fills the data with a fancy pattern if ( ((i*j)/8) % 2 ) pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255,255,0,255); else pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255, 255 - (j * 2), 255 - i, 255 - (i * 2)); } } /* The data in the array is then copied to the portion of the image starting at (0,0) through to (IMG_SIZE, IMG_SIZE), in this case that is the whole image. The coordinate system of the image places (0,0) at the bottom left-hand corner and (IMG_SIZE, IMG_SIZE) at the top right-hand corner. */ vgImageSubData(m_avgImage[0],pui32ImgData, sizeof(VGuint) * IMG_SIZE,VG_sRGBA_8888, 0, 0, IMG_SIZE, IMG_SIZE); // Delete the image data as it is now in OpenVG memory delete[] pui32ImgData; pui32ImgData = 0; /* The second image will initially be cleared to a single colour and then a part of the first image will be copied to it. */ //The colour to clear the image to is taken from the currently set VG_CLEAR_COLOR. VGfloat afClearColour[] = { 1.0f, 0.8f, 0.6f, 1.0f }; vgSetfv(VG_CLEAR_COLOR, 4, afClearColour); //Clear the part of the image in the range (0,0) to (IMG_SIZE, IMG_SIZE), in this case that is the whole image. vgClearImage(m_avgImage[1], 0, 0, IMG_SIZE, IMG_SIZE); /* Copy the bottom left-hand corner ((0,0) to (IMG_SIZE / 2, IMG_SIZE / 2)) of the first image into the the second image starting at (IMG_SIZE / 4, IMG_SIZE / 4). */ int i32ImgSizeQuarter = (int) (IMG_SIZE * 0.25); vgCopyImage(m_avgImage[1], i32ImgSizeQuarter, i32ImgSizeQuarter, m_avgImage[0], 0,0, (VGint) (IMG_SIZE * 0.5), (VGint) (IMG_SIZE * 0.5), (VGboolean) false); //Set the clear colour for clearing the sceen afClearColour[0] = 0.6f; afClearColour[1] = 0.8f; afClearColour[2] = 1.0f; afClearColour[3] = 1.0f; vgSetfv(VG_CLEAR_COLOR, 4, afClearColour); m_PrintVG.Initialize(PVRShellGet(prefWidth), PVRShellGet(prefHeight)); return true; }
static void *vg_init(const video_info_t *video, const input_driver_t **input, void **input_data) { vg_t *vg = (vg_t*)calloc(1, sizeof(vg_t)); if (!vg) return NULL; vg->driver = gfx_ctx_init_first(GFX_CTX_OPENVG_API, 0, 0); if (!vg->driver) { free(vg); return NULL; } vg->driver->get_video_size(&vg->mScreenWidth, &vg->mScreenHeight); RARCH_LOG("Detecting screen resolution %ux%u.\n", vg->mScreenWidth, vg->mScreenHeight); vg->driver->swap_interval(video->vsync ? 1 : 0); vg->driver->update_window_title(); vg->mTexType = video->rgb32 ? VG_sXRGB_8888 : VG_sRGB_565; vg->mKeepAspect = video->force_aspect; unsigned win_width = video->width; unsigned win_height = video->height; if (video->fullscreen && (win_width == 0) && (win_height == 0)) { win_width = vg->mScreenWidth; win_height = vg->mScreenHeight; } if (!vg->driver->set_video_mode(win_width, win_height, video->fullscreen)) { free(vg); return NULL; } vg->driver->get_video_size(&vg->mScreenWidth, &vg->mScreenHeight); RARCH_LOG("Verified window resolution %ux%u.\n", vg->mScreenWidth, vg->mScreenHeight); vg->should_resize = true; if (vg->driver->translate_aspect) vg->mScreenAspect = vg->driver->translate_aspect(vg->mScreenWidth, vg->mScreenHeight); else vg->mScreenAspect = (float)vg->mScreenWidth / vg->mScreenHeight; VGfloat clearColor[4] = {0, 0, 0, 1}; vgSetfv(VG_CLEAR_COLOR, 4, clearColor); vg->mTextureWidth = vg->mTextureHeight = video->input_scale * RARCH_SCALE_BASE; vg->mImage = vgCreateImage(vg->mTexType, vg->mTextureWidth, vg->mTextureHeight, video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED); vg_set_nonblock_state(vg, !video->vsync); vg->driver->input_driver(input, input_data); if (g_settings.video.font_enable && font_renderer_create_default(&vg->font_driver, &vg->mFontRenderer)) { vg->mFont = vgCreateFont(0); if (vg->mFont != VG_INVALID_HANDLE) { vg->mFontsOn = true; vg->mFontHeight = g_settings.video.font_size * (g_settings.video.font_scale ? (float) vg->mScreenWidth / 1280.0f : 1.0f); vg->mPaintFg = vgCreatePaint(); vg->mPaintBg = vgCreatePaint(); VGfloat paintFg[] = { g_settings.video.msg_color_r, g_settings.video.msg_color_g, g_settings.video.msg_color_b, 1.0f }; VGfloat paintBg[] = { g_settings.video.msg_color_r / 2.0f, g_settings.video.msg_color_g / 2.0f, g_settings.video.msg_color_b / 2.0f, 0.5f }; vgSetParameteri(vg->mPaintFg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(vg->mPaintFg, VG_PAINT_COLOR, 4, paintFg); vgSetParameteri(vg->mPaintBg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(vg->mPaintBg, VG_PAINT_COLOR, 4, paintBg); } } if (vg_query_extension("KHR_EGL_image") && vg->driver->init_egl_image_buffer(video)) { pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)vg->driver->get_proc_address("vgCreateEGLImageTargetKHR"); if (pvgCreateEGLImageTargetKHR) { RARCH_LOG("[VG] Using EGLImage buffer\n"); vg->mEglImageBuf = true; } } #if 0 const char *ext = (const char*)vgGetString(VG_EXTENSIONS); if (ext) RARCH_LOG("[VG] Supported extensions: %s\n", ext); #endif return vg; }
// createImageFromJpeg decompresses a JPEG image to the standard image format // source: https://github.com/ileben/ShivaVG/blob/master/examples/test_image.c VGImage createImageFromJpeg(const char *filename) { FILE *infile; struct jpeg_decompress_struct jdc; struct jpeg_error_mgr jerr; JSAMPARRAY buffer; unsigned int bstride; unsigned int bbpp; VGImage img; VGubyte *data; unsigned int width; unsigned int height; unsigned int dstride; unsigned int dbpp; VGubyte *brow; VGubyte *drow; unsigned int x; unsigned int lilEndianTest = 1; VGImageFormat rgbaFormat; // Check for endianness if (((unsigned char *)&lilEndianTest)[0] == 1) rgbaFormat = VG_sABGR_8888; else rgbaFormat = VG_sRGBA_8888; // Try to open image file infile = fopen(filename, "rb"); if (infile == NULL) { printf("Failed opening '%s' for reading!\n", filename); return VG_INVALID_HANDLE; } // Setup default error handling jdc.err = jpeg_std_error(&jerr); jpeg_create_decompress(&jdc); // Set input file jpeg_stdio_src(&jdc, infile); // Read header and start jpeg_read_header(&jdc, TRUE); jpeg_start_decompress(&jdc); width = jdc.output_width; height = jdc.output_height; // Allocate buffer using jpeg allocator bbpp = jdc.output_components; bstride = width * bbpp; buffer = (*jdc.mem->alloc_sarray) ((j_common_ptr) & jdc, JPOOL_IMAGE, bstride, 1); // Allocate image data buffer dbpp = 4; dstride = width * dbpp; data = (VGubyte *) malloc(dstride * height); // Iterate until all scanlines processed while (jdc.output_scanline < height) { // Read scanline into buffer jpeg_read_scanlines(&jdc, buffer, 1); drow = data + (height - jdc.output_scanline) * dstride; brow = buffer[0]; // Expand to RGBA for (x = 0; x < width; ++x, drow += dbpp, brow += bbpp) { switch (bbpp) { case 4: drow[0] = brow[0]; drow[1] = brow[1]; drow[2] = brow[2]; drow[3] = brow[3]; break; case 3: drow[0] = brow[0]; drow[1] = brow[1]; drow[2] = brow[2]; drow[3] = 255; break; } } } // Create VG image img = vgCreateImage(rgbaFormat, width, height, VG_IMAGE_QUALITY_BETTER); vgImageSubData(img, data, dstride, rgbaFormat, 0, 0, width, height); // Cleanup jpeg_destroy_decompress(&jdc); fclose(infile); free(data); return img; }
/******************************************************************************* * Function Name : InitView * Returns : true if no error occured * Description : Code in InitView() will be called by the Shell upon a change * in the rendering context. * Used to initialise variables that are dependent on the rendering * context (e.g. textures, vertex buffers, etc.) *******************************************************************************/ bool CChildImage::InitView() { //Create an image m_vgImage = vgCreateImage(VG_sRGBA_8888, IMG_SIZE, IMG_SIZE, VG_IMAGE_QUALITY_NONANTIALIASED); /* Populate the image from memory. A 32bit integer array (8bits per component) is created and populated. */ VGuint* pui32ImgData = new VGuint[IMG_SIZE*IMG_SIZE]; for(int i = 0; i < IMG_SIZE; ++i) { for(int j = 0; j < IMG_SIZE; ++j) { // Fills the data with a fancy pattern if ( ((i*j)/8) % 2 ) pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255,255,0,255); else pui32ImgData[j*IMG_SIZE+i] = PVRTRGBA(255, 255 - (j * 2), 255 - i, 255 - (i * 2)); } } /* The data in the array is then copied to the portion of the image starting at (0,0) through to (IMG_SIZE, IMG_SIZE), in this case that is the whole image. The coordinate system of the image places (0,0) at the bottom left-hand corner and (IMG_SIZE, IMG_SIZE) at the top right-hand corner. */ vgImageSubData(m_vgImage, pui32ImgData, sizeof(VGuint) * IMG_SIZE, VG_sRGBA_8888, 0, 0, IMG_SIZE, IMG_SIZE); // Delete the image data as it is now in OpenVG memory delete[] pui32ImgData; pui32ImgData = 0; //Create child images /* The first child is a child of m_vgImage and is made up of the region of m_vgImage from (0,0) to (IMG_SIZE / 2, IMG_SIZE / 2). Note: The area specified must be in the bounds of the parent. */ m_avgChildImages[0] = vgChildImage(m_vgImage, 0, 0, (VGint) (IMG_SIZE * 0.5), (VGint) (IMG_SIZE * 0.5)); //The second child is a clone of the first child. //Get the dimensions of the first child.. int i32ChildWidth = vgGetParameteri(m_avgChildImages[0], VG_IMAGE_WIDTH); int i32ChildHeight= vgGetParameteri(m_avgChildImages[0], VG_IMAGE_HEIGHT); //..and use them to define the region for creating the second child. m_avgChildImages[1] = vgChildImage(m_avgChildImages[0], 0, 0, i32ChildWidth, i32ChildHeight); /* Clear a small portion of the bottom left-hand corner of m_avgChildImages[0] to red. This change will be seen in all relatives of m_avgChildImages[0], reason being they all share the same physical memory. Note: When clearing you specify the coordinate you want to start from and then how many pixels across and up you want to clear. */ VGfloat afClearColour[] = {1.0f, 0.0f, 0.0f, 1.0f}; vgSetfv(VG_CLEAR_COLOR, 4, afClearColour); vgClearImage(m_avgChildImages[0], 0, 0, 10, 10); //Set the clear colour for clearing the sceen afClearColour[0] = 0.6f; afClearColour[1] = 0.8f; afClearColour[2] = 1.0f; afClearColour[3] = 1.0f; vgSetfv(VG_CLEAR_COLOR, 4, afClearColour); m_PrintVG.Initialize(PVRShellGet(prefWidth), PVRShellGet(prefHeight)); return true; }
void SubtitleRenderer::load_glyph(char32_t codepoint) { VGfloat escapement[2]{}; auto load_glyph_internal = [&](FT_Face ft_face, VGFont vg_font, bool border) { try { auto glyph_index = FT_Get_Char_Index(ft_face, codepoint); ENFORCE(!FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_NO_HINTING)); FT_Glyph glyph; ENFORCE(!FT_Get_Glyph(ft_face->glyph, &glyph)); SCOPE_EXIT {FT_Done_Glyph(glyph);}; if (border) ENFORCE(!FT_Glyph_StrokeBorder(&glyph, ft_stroker_, 0, 1)); ENFORCE(!FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, NULL, 1)); FT_BitmapGlyph bit_glyph = (FT_BitmapGlyph) glyph; FT_Bitmap& bitmap = bit_glyph->bitmap; VGImage image{}; VGfloat glyph_origin[2]{}; if (bitmap.width > 0 && bitmap.rows > 0) { constexpr VGfloat blur_stddev = 0.6; const int padding = static_cast<int>(3*blur_stddev + 0.5); const int image_width = bitmap.width + padding*2; const int image_height = bitmap.rows + padding*2; image = vgCreateImage(VG_A_8, image_width, image_height, VG_IMAGE_QUALITY_NONANTIALIASED); assert(image); if (bitmap.pitch > 0) { vgImageSubData(image, bitmap.buffer + bitmap.pitch*(bitmap.rows-1), -bitmap.pitch, VG_A_8, padding, padding, bitmap.width, bitmap.rows); assert(!vgGetError()); } else { vgImageSubData(image, bitmap.buffer, bitmap.pitch, VG_A_8, padding, padding, bitmap.width, bitmap.rows); assert(!vgGetError()); } auto softened_image = vgCreateImage(VG_A_8, image_width, image_height, VG_IMAGE_QUALITY_NONANTIALIASED); assert(image); // Even out hard and soft edges vgGaussianBlur(softened_image, image, blur_stddev, blur_stddev, VG_TILE_FILL); assert(!vgGetError()); vgDestroyImage(image); assert(!vgGetError()); image = softened_image; glyph_origin[0] = static_cast<VGfloat>(padding - bit_glyph->left); glyph_origin[1] = static_cast<VGfloat>(padding + bitmap.rows - bit_glyph->top - 1); } escapement[0] = static_cast<VGfloat>((ft_face->glyph->advance.x + 32) / 64); escapement[1] = 0; vgSetGlyphToImage(vg_font, codepoint, image, glyph_origin, escapement); assert(!vgGetError()); if (image) { vgDestroyImage(image); assert(!vgGetError()); } } catch(...) { escapement[0] = 0; escapement[1] = 0; vgSetGlyphToImage(vg_font, codepoint, VG_INVALID_HANDLE, escapement, escapement); assert(!vgGetError()); } }; load_glyph_internal(ft_face_, vg_font_, false); glyphs_[codepoint].advance = escapement[0]; load_glyph_internal(ft_face_, vg_font_border_, true); }
static void *rpi_init(const video_info_t *video, const input_driver_t **input, void **input_data) { int32_t success; EGLBoolean result; EGLint num_config; rpi_t *rpi = (rpi_t*)calloc(1, sizeof(rpi_t)); *input = NULL; static EGL_DISPMANX_WINDOW_T nativewindow; DISPMANX_ELEMENT_HANDLE_T dispman_element; DISPMANX_DISPLAY_HANDLE_T dispman_display; DISPMANX_UPDATE_HANDLE_T dispman_update; DISPMANX_MODEINFO_T dispman_modeinfo; VC_RECT_T dst_rect; VC_RECT_T src_rect; static const EGLint attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; EGLConfig config; bcm_host_init(); // get an EGL display connection rpi->mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); rarch_assert(rpi->mDisplay != EGL_NO_DISPLAY); // initialize the EGL display connection result = eglInitialize(rpi->mDisplay, NULL, NULL); rarch_assert(result != EGL_FALSE); eglBindAPI(EGL_OPENVG_API); // get an appropriate EGL frame buffer configuration result = eglChooseConfig(rpi->mDisplay, attribute_list, &config, 1, &num_config); rarch_assert(result != EGL_FALSE); // create an EGL rendering context rpi->mContext = eglCreateContext(rpi->mDisplay, config, EGL_NO_CONTEXT, NULL); rarch_assert(rpi->mContext != EGL_NO_CONTEXT); // create an EGL window surface success = graphics_get_display_size(0 /* LCD */, &rpi->mScreenWidth, &rpi->mScreenHeight); rarch_assert(success >= 0); dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = rpi->mScreenWidth; dst_rect.height = rpi->mScreenHeight; src_rect.x = 0; src_rect.y = 0; src_rect.width = rpi->mScreenWidth << 16; src_rect.height = rpi->mScreenHeight << 16; dispman_display = vc_dispmanx_display_open(0 /* LCD */); vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo); dispman_update = vc_dispmanx_update_start(0); dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer*/, &dst_rect, 0 /*src*/, &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0 /*clamp*/, DISPMANX_NO_ROTATE); nativewindow.element = dispman_element; nativewindow.width = rpi->mScreenWidth; nativewindow.height = rpi->mScreenHeight; vc_dispmanx_update_submit_sync(dispman_update); rpi->mSurface = eglCreateWindowSurface(rpi->mDisplay, config, &nativewindow, NULL); rarch_assert(rpi->mSurface != EGL_NO_SURFACE); // connect the context to the surface result = eglMakeCurrent(rpi->mDisplay, rpi->mSurface, rpi->mSurface, rpi->mContext); rarch_assert(result != EGL_FALSE); rpi->mTexType = video->rgb32 ? VG_sABGR_8888 : VG_sARGB_1555; rpi->mKeepAspect = video->force_aspect; // check for SD televisions: they should always be 4:3 if (dispman_modeinfo.width == 720 && (dispman_modeinfo.height == 480 || dispman_modeinfo.height == 576)) rpi->mScreenAspect = 4.0f / 3.0f; else rpi->mScreenAspect = (float)dispman_modeinfo.width / dispman_modeinfo.height; VGfloat clearColor[4] = {0, 0, 0, 1}; vgSetfv(VG_CLEAR_COLOR, 4, clearColor); rpi->mTextureWidth = rpi->mTextureHeight = video->input_scale * RARCH_SCALE_BASE; // We can't use the native format because there's no sXRGB_1555 type and // emulation cores can send 0 in the top bit. We lose some speed on // conversion but I doubt it has any real affect, since we are only drawing // one image at the end of the day. Still keep the alpha channel for ABGR. rpi->mImage = vgCreateImage(video->rgb32 ? VG_sABGR_8888 : VG_sXBGR_8888, rpi->mTextureWidth, rpi->mTextureHeight, video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED); rpi_set_nonblock_state(rpi, !video->vsync); linuxraw_input_t *linuxraw_input = (linuxraw_input_t*)input_linuxraw.init(); if (linuxraw_input) { *input = (const input_driver_t *)&input_linuxraw; *input_data = linuxraw_input; } #ifdef HAVE_FREETYPE if (g_settings.video.font_enable) { rpi->mFont = vgCreateFont(0); rpi->mFontHeight = g_settings.video.font_size * (g_settings.video.font_scale ? (float) rpi->mScreenWidth / 1280.0f : 1.0f); const char *path = g_settings.video.font_path; if (!*path || !path_file_exists(path)) path = font_renderer_get_default_font(); rpi->mFontRenderer = font_renderer_new(path, rpi->mFontHeight); if (rpi->mFont != VG_INVALID_HANDLE && rpi->mFontRenderer) { rpi->mFontsOn = true; rpi->mPaintFg = vgCreatePaint(); rpi->mPaintBg = vgCreatePaint(); VGfloat paintFg[] = { g_settings.video.msg_color_r, g_settings.video.msg_color_g, g_settings.video.msg_color_b, 1.0f }; VGfloat paintBg[] = { g_settings.video.msg_color_r / 2.0f, g_settings.video.msg_color_g / 2.0f, g_settings.video.msg_color_b / 2.0f, 0.5f }; vgSetParameteri(rpi->mPaintFg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(rpi->mPaintFg, VG_PAINT_COLOR, 4, paintFg); vgSetParameteri(rpi->mPaintBg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(rpi->mPaintBg, VG_PAINT_COLOR, 4, paintBg); } } #endif struct sigaction sa; sa.sa_handler = rpi_kill; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); return rpi; }