static DFBResult InitPVR2D( PVR2DData *pvr2d ) { PVR2DERROR ePVR2DStatus; PVR2DDataShared *shared = pvr2d->shared; pvr2d->nDevices = PVR2DEnumerateDevices(0); pvr2d->pDevInfo = (PVR2DDEVICEINFO *) malloc(pvr2d->nDevices * sizeof(PVR2DDEVICEINFO)); PVR2DEnumerateDevices(pvr2d->pDevInfo); pvr2d->nDeviceNum = pvr2d->pDevInfo[0].ulDevID; ePVR2DStatus = PVR2DCreateDeviceContext (pvr2d->nDeviceNum, &pvr2d->hPVR2DContext, 0); if (ePVR2DStatus) { D_ERROR( "DirectFB/PVR2D: PVR2DCreateDeviceContext() failed! (status %d)\n", ePVR2DStatus ); return DFB_INIT; } ePVR2DStatus = PVR2DGetFrameBuffer( pvr2d->hPVR2DContext, PVR2D_FB_PRIMARY_SURFACE, &pvr2d->pFBMemInfo); if (ePVR2DStatus) { D_ERROR( "DirectFB/PVR2D: PVR2DGetFrameBuffer() failed! (status %d)\n", ePVR2DStatus ); return DFB_INIT; } ePVR2DStatus = PVR2DGetScreenMode(pvr2d->hPVR2DContext, &pvr2d->eDisplayFormat, &pvr2d->lDisplayWidth, &pvr2d->lDisplayHeight, &pvr2d->lStride, &pvr2d->RefreshRate); if (ePVR2DStatus) { D_ERROR( "DirectFB/PVR2D: PVR2DGetScreenMode() failed! (status %d)\n", ePVR2DStatus ); return DFB_INIT; } D_INFO( "DirectFB/PVR2D: Display %ldx%ld, format %d, stride %ld, refresh %d\n", pvr2d->lDisplayWidth, pvr2d->lDisplayHeight, pvr2d->eDisplayFormat, pvr2d->lStride, pvr2d->RefreshRate ); shared->screen_size.w = pvr2d->lDisplayWidth; shared->screen_size.h = pvr2d->lDisplayHeight; return DFB_OK; }
/* Called when a new drawable is added to ensure that we have a PVR2D context and framebuffer PVR2DMEMINFO blocks */ static int pvrQwsAddDrawable(void) { int numDevs, screen; PVR2DDEVICEINFO *devs; unsigned long devId; unsigned long pageAddresses[2]; PVR2DMEMINFO *memInfo; PVR2DDISPLAYINFO displayInfo; /* Bail out early if this is not the first drawable */ if (pvrQwsDisplay.numDrawables > 0) { ++(pvrQwsDisplay.numDrawables); return 1; } /* Find the first PVR2D device in the system and open it */ numDevs = PVR2DEnumerateDevices(0); if (numDevs <= 0) return 0; devs = (PVR2DDEVICEINFO *)malloc(sizeof(PVR2DDEVICEINFO) * numDevs); if (!devs) return 0; if (PVR2DEnumerateDevices(devs) != PVR2D_OK) { free(devs); return 0; } devId = devs[0].ulDevID; free(devs); if (PVR2DCreateDeviceContext(devId, &pvrQwsDisplay.context, 0) != PVR2D_OK) return 0; pvrQwsDisplay.numFlipBuffers = 0; pvrQwsDisplay.flipChain = 0; if (PVR2DGetDeviceInfo(pvrQwsDisplay.context, &displayInfo) == PVR2D_OK) { if (displayInfo.ulMaxFlipChains > 0 && displayInfo.ulMaxBuffersInChain > 0) pvrQwsDisplay.numFlipBuffers = displayInfo.ulMaxBuffersInChain; if (pvrQwsDisplay.numFlipBuffers > PVRQWS_MAX_FLIP_BUFFERS) pvrQwsDisplay.numFlipBuffers = PVRQWS_MAX_FLIP_BUFFERS; } /* Create the PVR2DMEMINFO blocks for the active framebuffers */ for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) { if (screen != 0 && pvrQwsDisplay.screens[screen].mapped) { pageAddresses[0] = pvrQwsDisplay.screens[screen].screenStart & 0xFFFFF000; pageAddresses[1] = 0; if (PVR2DMemWrap (pvrQwsDisplay.context, pvrQwsDisplay.screens[screen].mapped, PVR2D_WRAPFLAG_CONTIGUOUS, pvrQwsDisplay.screens[screen].mappedLength, pageAddresses, &memInfo) != PVR2D_OK) { PVR2DDestroyDeviceContext(pvrQwsDisplay.context); pvrQwsDisplay.context = 0; return 0; } pvrQwsDisplay.screens[screen].frameBuffer = memInfo; } else if (screen == 0) { if (PVR2DGetFrameBuffer (pvrQwsDisplay.context, PVR2D_FB_PRIMARY_SURFACE, &memInfo) != PVR2D_OK) { fprintf(stderr, "QWSWSEGL: could not get the primary framebuffer surface\n"); PVR2DDestroyDeviceContext(pvrQwsDisplay.context); pvrQwsDisplay.context = 0; return 0; } pvrQwsDisplay.screens[screen].frameBuffer = memInfo; pvrQwsDisplay.screens[screen].mapped = memInfo->pBase; } } /* Create a flip chain for the screen if supported by the hardware */ pvrQwsDisplay.usePresentBlit = 0; if (pvrQwsDisplay.numFlipBuffers > 0) { long stride = 0; unsigned long flipId = 0; unsigned long numBuffers; if (PVR2DCreateFlipChain(pvrQwsDisplay.context, 0, //PVR2D_CREATE_FLIPCHAIN_SHARED | //PVR2D_CREATE_FLIPCHAIN_QUERY, pvrQwsDisplay.numFlipBuffers, pvrQwsDisplay.screens[0].screenRect.width, pvrQwsDisplay.screens[0].screenRect.height, pvrQwsDisplay.screens[0].pixelFormat, &stride, &flipId, &(pvrQwsDisplay.flipChain)) == PVR2D_OK) { pvrQwsDisplay.screens[0].screenStride = stride; PVR2DGetFlipChainBuffers(pvrQwsDisplay.context, pvrQwsDisplay.flipChain, &numBuffers, pvrQwsDisplay.flipBuffers); } else { pvrQwsDisplay.flipChain = 0; pvrQwsDisplay.numFlipBuffers = 0; } /* PVR2DPresentBlt is a little more reliable than PVR2DBlt when flip chains are present, even if we cannot create a flip chain at the moment */ pvrQwsDisplay.usePresentBlit = 1; } /* The context is ready to go */ ++(pvrQwsDisplay.numDrawables); return 1; }
/* Create the WSEGL drawable version of a native window */ static WSEGLError wseglCreateWindowDrawable (WSEGLDisplayHandle display, WSEGLConfig *config, WSEGLDrawableHandle *drawable, NativeWindowType nativeWindow, WSEGLRotationAngle *rotationAngle) { struct wl_egl_display *egldisplay = (struct wl_egl_display *) display; int index; /* Framebuffer */ if (nativeWindow == NULL) { PVR2DDISPLAYINFO displayInfo; assert(egldisplay->display == NULL); /* Let's create a fake wl_egl_window to simplify code */ nativeWindow = wl_egl_window_create(NULL, egldisplay->var.xres, egldisplay->var.yres); nativeWindow->format = getwseglPixelFormat(egldisplay); nativeWindow->display = egldisplay; assert(PVR2DGetDeviceInfo(egldisplay->context, &displayInfo) == PVR2D_OK); wsegl_debug("ulMaxFlipChains: %lu", displayInfo.ulMaxFlipChains); wsegl_debug("ulMaxBuffersInChain: %lu", displayInfo.ulMaxBuffersInChain); wsegl_debug("eFormat: %d", displayInfo.eFormat); wsegl_debug("ulWidth: %lu", displayInfo.ulWidth); wsegl_debug("ulHeight: %lu", displayInfo.ulHeight); wsegl_debug("lStride: %lu", displayInfo.lStride); wsegl_debug("ulMinFlipInterval: %lu", displayInfo.ulMinFlipInterval); wsegl_debug("ulMaxFlipInterval: %lu", displayInfo.ulMaxFlipInterval); if (displayInfo.ulMaxFlipChains > 0 && displayInfo.ulMaxBuffersInChain > 0) nativeWindow->numFlipBuffers = displayInfo.ulMaxBuffersInChain; if (nativeWindow->numFlipBuffers > WAYLANDWSEGL_MAX_FLIP_BUFFERS) nativeWindow->numFlipBuffers = WAYLANDWSEGL_MAX_FLIP_BUFFERS; /* Workaround for broken devices, seen in debugging */ // if (nativeWindow->numFlipBuffers < 2) nativeWindow->numFlipBuffers = 0; } else { nativeWindow->display = egldisplay; nativeWindow->format = config->ePixelFormat; } /* We can't do empty buffers, so let's make a 8x8 one. */ if (nativeWindow->width == 0 || nativeWindow->height == 0) { nativeWindow->width = nativeWindow->height = 8; } /* If we don't have back buffers allocated already */ if (!(nativeWindow->backBuffers[0] && nativeWindow->backBuffersValid)) { nativeWindow->stridePixels = (nativeWindow->width + 7) & ~7; nativeWindow->strideBytes = nativeWindow->stridePixels * wseglPixelFormatBytesPP(nativeWindow->format); if (allocateBackBuffers(egldisplay, nativeWindow) == WSEGL_OUT_OF_MEMORY) return WSEGL_OUT_OF_MEMORY; /* Wayland window */ if (nativeWindow->display->display != NULL) { for (index = 0; index < WAYLANDWSEGL_MAX_BACK_BUFFERS; index++) { PVR2D_HANDLE name; assert(PVR2DMemExport(egldisplay->context, 0, nativeWindow->backBuffers[index], &name) == PVR2D_OK); nativeWindow->exporthandles[index] = name; // TODO: clear exporthandles up } } /* Framebuffer */ else { /* XXX should assert something about stride etc.. */ assert(PVR2DGetFrameBuffer(egldisplay->context, PVR2D_FB_PRIMARY_SURFACE, &nativeWindow->frontBufferPVRMEM) == PVR2D_OK); // nativeWindow->frontBuffer = (void *) nativeWindow->frontBufferPVRMEM->pBase; } } *drawable = (WSEGLDrawableHandle) nativeWindow; /* Reuse the egldisplay */ *rotationAngle = WSEGL_ROTATE_0; return WSEGL_SUCCESS; }
/* Create the WSEGL drawable version of a native window */ static WSEGLError wseglCreateWindowDrawable (WSEGLDisplayHandle display, WSEGLConfig *config, WSEGLDrawableHandle *drawable, NativeWindowType nativeWindow, WSEGLRotationAngle *rotationAngle) { struct wl_egl_display *egldisplay = (struct wl_egl_display *) display; int index; /* Framebuffer */ if (nativeWindow == NULL) { PVR2DDISPLAYINFO displayInfo; assert(egldisplay->display == NULL); /* Let's create a fake wl_egl_window to simplify code */ nativeWindow = wl_egl_window_create(NULL, egldisplay->var.xres, egldisplay->var.yres); nativeWindow->format = getwseglPixelFormat(egldisplay); nativeWindow->display = egldisplay; assert(PVR2DGetDeviceInfo(egldisplay->context, &displayInfo) == PVR2D_OK); if (displayInfo.ulMaxFlipChains > 0 && displayInfo.ulMaxBuffersInChain > 0) nativeWindow->numFlipBuffers = displayInfo.ulMaxBuffersInChain; if (nativeWindow->numFlipBuffers > WAYLANDWSEGL_MAX_FLIP_BUFFERS) nativeWindow->numFlipBuffers = WAYLANDWSEGL_MAX_FLIP_BUFFERS; /* Workaround for broken devices, seen in debugging */ if (nativeWindow->numFlipBuffers < 2) nativeWindow->numFlipBuffers = 0; } else { nativeWindow->display = egldisplay; nativeWindow->format = WSEGL_PIXELFORMAT_8888; } /* We can't do empty buffers, so let's make a 8x8 one. */ if (nativeWindow->width == 0 || nativeWindow->height == 0) { nativeWindow->width = nativeWindow->height = 8; } /* If we don't have back buffers allocated already */ if (!(nativeWindow->backBuffers[0] && nativeWindow->backBuffersValid)) { nativeWindow->stridePixels = (nativeWindow->width + 7) & ~7; nativeWindow->strideBytes = nativeWindow->stridePixels * wseglPixelFormatBytesPP(nativeWindow->format); if (allocateBackBuffers(egldisplay, nativeWindow) == WSEGL_OUT_OF_MEMORY) return WSEGL_OUT_OF_MEMORY; /* Wayland window */ if (nativeWindow->display->display != NULL) { for (index = 0; index < WAYLANDWSEGL_MAX_BACK_BUFFERS; index++) { PVR2D_HANDLE name; assert(PVR2DMemExport(egldisplay->context, 0, nativeWindow->backBuffers[index], &name) == PVR2D_OK); nativeWindow->drmbuffers[index] = wl_drm_create_buffer(egldisplay->drm, (uint32_t)name, nativeWindow->width, nativeWindow->height, nativeWindow->strideBytes, nativeWindow->format); assert(nativeWindow->drmbuffers[index] != NULL); } } /* Framebuffer */ else { assert(PVR2DGetFrameBuffer(egldisplay->context, PVR2D_FB_PRIMARY_SURFACE, &nativeWindow->frontBufferPVRMEM) == PVR2D_OK); } } *drawable = (WSEGLDrawableHandle) nativeWindow; /* Reuse the egldisplay */ *rotationAngle = WSEGL_ROTATE_0; return WSEGL_SUCCESS; }