static GstDucatiBuffer * gst_ducati_buffer_new (GstPvrBufferPool * pool) { PVR2DERROR pvr_error; GstDucatiBuffer *self = (GstDucatiBuffer *) gst_mini_object_new (GST_TYPE_DUCATIBUFFER); GST_LOG_OBJECT (pool->element, "creating buffer %p in pool %p", self, pool); self->pool = (GstPvrBufferPool *) gst_mini_object_ref (GST_MINI_OBJECT (pool)); GST_BUFFER_DATA (self) = gst_ducati_alloc_1d (pool->size); GST_BUFFER_SIZE (self) = pool->size; GST_LOG_OBJECT (pool->element, "width=%d, height=%d and size=%d", pool->padded_width, pool->padded_height, pool->size); pvr_error = PVR2DMemWrap (pool->pvr_context, GST_BUFFER_DATA (self), 0, pool->size, NULL, &(self->src_mem)); if (pvr_error != PVR2D_OK) { GST_LOG_OBJECT (pool->element, "Failed to Wrap buffer memory" "returned %d", pvr_error); } else { self->wrapped = TRUE; } gst_buffer_set_caps (GST_BUFFER (self), pool->caps); return self; }
/* Initialize the /dev/fbN device for a specific screen */ static int pvrQwsInitFbScreen(int screen) { struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; unsigned long start; unsigned long length; int width, height, stride; PVR2DFORMAT format; void *mapped; int fd, bytesPerPixel; char name[64]; PVR2DMEMINFO *memInfo; unsigned long pageAddresses[2]; /* Bail out if already initialized, or the number is incorrect */ if (screen < 0 || screen >= PVRQWS_MAX_SCREENS) return 0; if (pvrQwsDisplay.screens[screen].initialized) return 1; /* Open the framebuffer and fetch its properties */ sprintf(name, "/dev/fb%d", screen); fd = open(name, O_RDWR, 0); if (fd < 0) { perror(name); return 0; } if (ioctl(fd, FBIOGET_VSCREENINFO, &var) < 0) { perror("FBIOGET_VSCREENINFO"); close(fd); return 0; } if (ioctl(fd, FBIOGET_FSCREENINFO, &fix) < 0) { perror("FBIOGET_FSCREENINFO"); close(fd); return 0; } width = var.xres; height = var.yres; bytesPerPixel = var.bits_per_pixel / 8; stride = var.xres * bytesPerPixel; format = PVR2D_1BPP; if (var.bits_per_pixel == 16) { if (var.red.length == 5 && var.green.length == 6 && var.blue.length == 5 && var.red.offset == 11 && var.green.offset == 5 && var.blue.offset == 0) { format = PVR2D_RGB565; } if (var.red.length == 4 && var.green.length == 4 && var.blue.length == 4 && var.transp.length == 4 && var.red.offset == 8 && var.green.offset == 4 && var.blue.offset == 0 && var.transp.offset == 12) { format = PVR2D_ARGB4444; } } else if (var.bits_per_pixel == 32) { if (var.red.length == 8 && var.green.length == 8 && var.blue.length == 8 && var.transp.length == 8 && var.red.offset == 16 && var.green.offset == 8 && var.blue.offset == 0 && var.transp.offset == 24) { format = PVR2D_ARGB8888; } } if (format == PVR2D_1BPP) { fprintf(stderr, "%s: could not find a suitable PVR2D pixel format\n", name); close(fd); return 0; } start = fix.smem_start; length = var.xres_virtual * var.yres_virtual * bytesPerPixel; if (screen == 0) { /* We use PVR2DGetFrameBuffer to map the first screen. On some chipsets it is more reliable than using PVR2DMemWrap */ mapped = 0; memInfo = 0; } else { /* Other screens: map the framebuffer region into memory */ mapped = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (!mapped || mapped == (void *)(-1)) { perror("mmap"); close(fd); return 0; } /* Allocate a PVR2D memory region for the framebuffer */ memInfo = 0; if (pvrQwsDisplay.context) { pageAddresses[0] = start & 0xFFFFF000; pageAddresses[1] = 0; if (PVR2DMemWrap (pvrQwsDisplay.context, mapped, PVR2D_WRAPFLAG_CONTIGUOUS, length, pageAddresses, &memInfo) != PVR2D_OK) { munmap(mapped, length); close(fd); return 0; } } } /* We don't need the file descriptor any more */ close(fd); /* The framebuffer is ready, so initialize the PvrQwsScreenInfo */ pvrQwsDisplay.screens[screen].screenRect.x = 0; pvrQwsDisplay.screens[screen].screenRect.y = 0; pvrQwsDisplay.screens[screen].screenRect.width = width; pvrQwsDisplay.screens[screen].screenRect.height = height; pvrQwsDisplay.screens[screen].screenStride = stride; pvrQwsDisplay.screens[screen].pixelFormat = format; pvrQwsDisplay.screens[screen].bytesPerPixel = bytesPerPixel; pvrQwsDisplay.screens[screen].screenDrawable = 0; if (mapped) { /* Don't set these fields if mapped is 0, because PVR2DGetFrameBuffer may have already been called and set them */ pvrQwsDisplay.screens[screen].frameBuffer = memInfo; pvrQwsDisplay.screens[screen].mapped = mapped; } pvrQwsDisplay.screens[screen].mappedLength = length; pvrQwsDisplay.screens[screen].screenStart = start; pvrQwsDisplay.screens[screen].needsUnmap = (mapped != 0); pvrQwsDisplay.screens[screen].initialized = 1; return 1; }
/* 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; }