Пример #1
0
static DisplayModePtr fbdev_lcd_output_get_modes(xf86OutputPtr output)
{
	MaliPtr fPtr = MALIPTR(output->scrn);
	DisplayModePtr mode_ptr;

	unsigned int hactive_s = fPtr->fb_lcd_var.xres;
	unsigned int vactive_s = fPtr->fb_lcd_var.yres;

	mode_ptr = xnfcalloc(1, sizeof(DisplayModeRec));

	mode_ptr->HDisplay = hactive_s;
	mode_ptr->HSyncStart = hactive_s + 20;
	mode_ptr->HSyncEnd = hactive_s + 40;
	mode_ptr->HTotal = hactive_s + 80;

	mode_ptr->VDisplay = vactive_s;
	mode_ptr->VSyncStart = vactive_s + 20;
	mode_ptr->VSyncEnd = vactive_s + 40;
	mode_ptr->VTotal = vactive_s + 80;

	mode_ptr->VRefresh = 60.0;

	mode_ptr->Clock = (int) (mode_ptr->VRefresh * mode_ptr->VTotal * mode_ptr->HTotal / 1000.0);

	mode_ptr->type = M_T_DRIVER;

	xf86SetModeDefaultName(mode_ptr);
		
	mode_ptr->next = NULL;
	mode_ptr->prev = NULL;

	return mode_ptr;
}
Пример #2
0
static int fbdev_lcd_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
	MaliPtr fPtr = MALIPTR(output->scrn);

	if( (pMode->HDisplay == (int)fPtr->fb_lcd_var.xres) && (pMode->VDisplay == (int)fPtr->fb_lcd_var.yres) ) return MODE_OK;

	return MODE_ERROR;
}
Пример #3
0
Bool maliSetupExa(ScreenPtr pScreen, ExaDriverPtr exa)
{
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	if (NULL == exa)
	{
		return FALSE;
	}

	TRACE_ENTER();

	exa->exa_major = 2;
	exa->exa_minor = 0;
	exa->memoryBase = fPtr->fbmem;
	exa->maxX = fPtr->fb_lcd_var.xres_virtual;
	exa->maxY = fPtr->fb_lcd_var.yres_virtual;
	exa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX;
	exa->offScreenBase = (fPtr->fb_lcd_fix.line_length * fPtr->fb_lcd_var.yres);
	exa->memorySize = fPtr->fb_lcd_fix.smem_len;
	exa->pixmapOffsetAlign = 4096;
	exa->pixmapPitchAlign = 8;

	MALI_EXA_FUNC(PrepareSolid);
	MALI_EXA_FUNC(Solid);
	MALI_EXA_FUNC(DoneSolid);

	MALI_EXA_FUNC(PrepareCopy);
	MALI_EXA_FUNC(Copy);
	MALI_EXA_FUNC(DoneCopy);

	MALI_EXA_FUNC(CheckComposite);
	MALI_EXA_FUNC(PrepareComposite);
	MALI_EXA_FUNC(Composite);
	MALI_EXA_FUNC(DoneComposite);

	MALI_EXA_FUNC(WaitMarker);

	MALI_EXA_FUNC(CreatePixmap);
	MALI_EXA_FUNC(DestroyPixmap);
	MALI_EXA_FUNC(ModifyPixmapHeader);
	MALI_EXA_FUNC(PixmapIsOffscreen);

	MALI_EXA_FUNC(PrepareAccess);
	MALI_EXA_FUNC(FinishAccess);

	if (UMP_OK != ump_open())
	{
		ERROR_MSG("failed to open UMP subsystem");
		TRACE_EXIT();
		return FALSE;
	}

	INFO_MSG("Mali EXA driver is loaded successfully");
	TRACE_EXIT();

	return TRUE;
}
Пример #4
0
static void maliFinishAccess(PixmapPtr pPix, int index)
{
	PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPix);
	mali_mem_info *mem_info;
	ScreenPtr pScreen = pPix->drawable.pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	IGNORE(index);

	if (!privPixmap)
	{
		return;
	}

	if (!pPix)
	{
		return;
	}

	mem_info = privPixmap->mem_info;

	if (!privPixmap->isFrameBuffer)
	{
		int secure_id = 0;
		_lock_item_s item;

		secure_id = ump_secure_id_get(mem_info->handle);

		if (secure_id)
		{
			item.secure_id = secure_id;
			item.usage = _LOCK_ACCESS_CPU_WRITE;

			if (fPtr->fd_umplock > 0)
			{
				ioctl(fPtr->fd_umplock, LOCK_IOCTL_RELEASE, &item);
			}
		}

		if (privPixmap->refs == 1)
		{
			if (NULL != mem_info)
			{
				ump_mapped_pointer_release(mem_info->handle);
			}
		}
	}

	pPix->devPrivate.ptr = NULL;
	privPixmap->refs--;
}
Пример #5
0
static void fbdev_lcd_output_dpms(xf86OutputPtr output, int mode)
{
	MaliPtr fPtr = MALIPTR(output->scrn);

	if ( mode == DPMSModeOn ) 
	{
		ioctl(fPtr->fb_lcd_fd, FBIOBLANK, FB_BLANK_UNBLANK);
	}
	else if( mode == DPMSModeOff )
	{
		ioctl(fPtr->fb_lcd_fd, FBIOBLANK, FB_BLANK_POWERDOWN);
	}
}
static void *maliCreatePixmap(ScreenPtr pScreen, int size, int align)
{
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	PrivPixmap *privPixmap = calloc(1, sizeof(PrivPixmap));

	if (NULL == privPixmap)
	{
		return NULL;
	}

	IGNORE(pScreen);
	IGNORE(size);
	IGNORE(align);

	privPixmap->isFrameBuffer  = FALSE;
	privPixmap->bits_per_pixel = 0;
	privPixmap->other_buffer   = NULL;

	return privPixmap;
}
Пример #7
0
static Bool maliPrepareAccess(PixmapPtr pPix, int index)
{
	ScreenPtr pScreen = pPix->drawable.pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPix);
	mali_mem_info *mem_info;

	IGNORE(index);

	if (!privPixmap)
	{
		ERROR_MSG("Failed to get private pixmap data");
		return FALSE;
	}

	mem_info = privPixmap->mem_info;

	if (NULL != mem_info)
	{
		if (privPixmap->refs == 0)
		{
			if (privPixmap->isFrameBuffer)
			{
				privPixmap->addr = (unsigned long)fPtr->fbmem;
			}
			else
			{
				privPixmap->addr = (unsigned long)ump_mapped_pointer_get(mem_info->handle);
			}

			privPixmap->addr += mem_info->offset;
		}
	}
	else
	{
		ERROR_MSG("No mem_info on pixmap");
		return FALSE;
	}

	pPix->devPrivate.ptr = (void *)(privPixmap->addr);

	if (NULL == pPix->devPrivate.ptr)
	{
		ERROR_MSG("cpu address not set");
		return FALSE;
	}

	privPixmap->refs++;

	if (!privPixmap->isFrameBuffer)
	{
		int secure_id = 0;
		_lock_item_s item;

		secure_id = ump_secure_id_get(mem_info->handle);

		if (secure_id)
		{
			item.secure_id = secure_id;
			item.usage = _LOCK_ACCESS_CPU_WRITE;

			if (fPtr->fd_umplock > 0)
			{
				ioctl(fPtr->fd_umplock, LOCK_IOCTL_CREATE, &item);

				if (ioctl(fPtr->fd_umplock, LOCK_IOCTL_PROCESS, &item) < 0)
				{
					int max_retries = 5;
					ERROR_MSG("Unable to process lock item with ID 0x%x - throttling\n", item.secure_id);

					while ((ioctl(fPtr->fd_umplock, LOCK_IOCTL_PROCESS, &item) < 0) && max_retries)
					{
						usleep(2000);
						max_retries--;
					}

					if (max_retries == 0)
					{
						ERROR_MSG("Warning: Max retries == 0\n");
					}
				}
			}

			if (fPtr->use_cached_ump)
			{
				ump_cache_operations_control(UMP_CACHE_OP_START);
				ump_switch_hw_usage_secure_id(item.secure_id, UMP_USED_BY_CPU);
				ump_cache_operations_control(UMP_CACHE_OP_FINISH);
			}
		}
	}

	return TRUE;
}
Пример #8
0
static Bool maliModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData)
{
	unsigned int size;
	PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPixmap);
	mali_mem_info *mem_info;
	ScreenPtr pScreen = pPixmap->drawable.pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	if (!pPixmap)
	{
		return FALSE;
	}

	miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData);

	if ((pPixData == fPtr->fbmem) || current_buf)
	{
		/* Wrap one of the fbdev virtual buffers */
		ump_secure_id ump_id = UMP_INVALID_SECURE_ID;

		privPixmap->isFrameBuffer = TRUE;
		privPixmap->frameBufferNumber = current_buf;
		mem_info = privPixmap->mem_info;

		if (mem_info)
		{
			return TRUE;
		}

		/* create new mem_info for the on-screen buffer */
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate for memory metadata");
			return FALSE;
		}

		/* get the secure ID for the framebuffers */
		if (ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF(current_buf), &ump_id) < 0
		        || UMP_INVALID_SECURE_ID == ump_id)
		{
			free(mem_info);
			privPixmap->mem_info = NULL;
			ERROR_MSG("UMP failed to retrieve secure id, current_buf: %d", current_buf);
			return FALSE;
		}

		INFO_MSG("GET_UMP_SECURE_ID_BUF(%d) returned 0x%x", current_buf, ump_id);

		mem_info->handle = ump_handle_create_from_secure_id(ump_id);

		if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
		{
			ERROR_MSG("UMP failed to create handle from secure id");
			free(mem_info);
			privPixmap->mem_info = NULL;
			return FALSE;
		}

		size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;
		mem_info->usize = size;

		privPixmap->mem_info = mem_info;

		if (bitsPerPixel != 0)
		{
			privPixmap->bits_per_pixel = bitsPerPixel;
		}

		/* When this is called directly from X to create the front buffer, current_buf is zero as expected. When this
		 * function is called recursively to create the back buffers, current_buf is increased to the next buffer */
		privPixmap->mem_info->offset = current_buf * size;

		if (pPixData == fPtr->fbmem)
		{
			/* This is executed only when this function is called directly from X. We need to create the other
			 * back buffers now because we can't "wrap" existing memory in a pixmap during DRI2CreateBuffer
			 * for the back buffer of the framebuffer. In DRI2CreateBuffer instead of allocating a new
			 * pixmap for the back buffer like we do for non-swappable windows, we'll just use the 'current_pixmap'
			 * to grab this pointer from the screen pixmap and return it. */

			PrivPixmap *current_privPixmap = privPixmap;
			int i;
			PrivBuffer *buf_info = calloc(1, sizeof(*buf_info));

			if (NULL == buf_info)
			{
				ERROR_MSG("Failed to allocate buf_info memory");
				free(mem_info);
				privPixmap->mem_info = NULL;
				return FALSE;
			}

			buf_info->current_pixmap = 0;
			buf_info->num_pixmaps = fPtr->dri2_num_buffers;
			buf_info->pPixmaps[0] = pPixmap;
			current_privPixmap->buf_info = buf_info;

			for (i = 1; i < buf_info->num_pixmaps; i++)
			{
				current_buf++;
				buf_info->pPixmaps[i] = (*pScreen->CreatePixmap)(pScreen, width, height, depth, 0);
				assert(buf_info->pPixmaps[i]);
				current_privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(buf_info->pPixmaps[i]);
				current_privPixmap->buf_info = buf_info;
			}

			current_buf = 0;
		}

		INFO_MSG("Creating FRAMEBUFFER pixmap %p at offset %lu, privPixmap=%p", pPixmap, privPixmap->mem_info->offset, privPixmap);

		return TRUE;
	}

	if (pPixData)
	{
		/* When this happens we're being told to wrap existing pixmap data for which we don't know the UMP
		 * handle. We can and still need to wrap it but it won't be offscreen - we can't accelerate it in any
		 * way. */

		if (privPixmap->mem_info != NULL)
		{
			return TRUE;
		}

		return FALSE;
	}

	pPixmap->devKind = ((pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel) + 7) / 8;
	pPixmap->devKind = MALI_ALIGN(pPixmap->devKind, 8);

	size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;

	/* allocate pixmap data */
	mem_info = privPixmap->mem_info;

	if (mem_info && mem_info->usize == size)
	{
		return TRUE;
	}

	if (mem_info && mem_info->usize != 0)
	{
		ump_reference_release(mem_info->handle);
		mem_info->handle = NULL;
		memset(privPixmap, 0, sizeof(*privPixmap));

		return TRUE;
	}

	if (!size)
	{
		return TRUE;
	}

	if (NULL == mem_info)
	{
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate memory metadata");
			return FALSE;
		}
	}

	if (fPtr->use_cached_ump)
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR | UMP_REF_DRV_CONSTRAINT_USE_CACHE);
	}
	else
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR);
	}

	if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
	{
		ERROR_MSG("failed to allocate UMP memory (%i bytes)", size);
		return FALSE;
	}

	mem_info->usize = size;
	privPixmap->mem_info = mem_info;
	privPixmap->mem_info->usize = size;
	privPixmap->bits_per_pixel = 16;

	return TRUE;
}
Пример #9
0
static void maliCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
{
	PrivPixmap *srcPrivPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(SrcPixmap);
	PrivPixmap *dstPrivPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pDstPixmap);


	IGNORE(pDstPixmap);
	IGNORE(srcX);
	IGNORE(srcY);
	IGNORE(dstX);
	IGNORE(dstY);
	IGNORE(width);
	IGNORE(height);


	//ERROR_STR("%s: pDstPixmap=%p srcX=%d srcY=%d dstX=%d dstY=%d width=%d height=%d\n",
	//	__FUNCTION__, pDstPixmap, srcX, srcY, dstX, dstY, width, height);


	ScreenPtr pScreen = SrcPixmap->drawable.pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	struct fb_var_screeninfo var_info;
	int ret = ioctl(fPtr->fb_lcd_fd, FBIOGET_VSCREENINFO, &var_info);
	if (ret < 0)
	{
		ERROR_STR("FBIOGET_VSCREENINFO failed.\n");
	}


	unsigned char revX = 0;
	unsigned char revY = 0;

	if (dstY > srcY)
	{
		revY = 1;
	}

	if (dstX > srcX)
	{
		revX = 1;
	}

	//if (srcPrivPixmap->frameBufferNumber != 0)
	//{
	//	srcY += (var_info.yres * srcPrivPixmap->frameBufferNumber);
	//}

	//if (dstPrivPixmap->frameBufferNumber != 0)
	//{
	//	dstY += (var_info.yres * dstPrivPixmap->frameBufferNumber);
	//}

	ump_secure_id srcID = ump_secure_id_get(srcPrivPixmap->mem_info->handle);

	memclient_attach_dmabuf_param_t srcParam;
	srcParam.handle = srcID;
	ret = ioctl(memclient_fd, MEMCLIENT_ATTACH_UMP, &srcParam);
	if (ret < 0)
	{
		ERROR_STR("srcParam MEMCLIENT_ATTACH_UMP failed.\n");
	}


	ump_secure_id dstID = ump_secure_id_get(dstPrivPixmap->mem_info->handle);

	memclient_attach_dmabuf_param_t dstParam;
	dstParam.handle = dstID;
	ret = ioctl(memclient_fd, MEMCLIENT_ATTACH_UMP, &dstParam);
	if (ret < 0)
	{
		ERROR_STR("dstParam MEMCLIENT_ATTACH_UMP failed.\n");
	}



	// Configure GE2D
	struct config_para_ex_s configex;
	memset(&configex, 0x00, sizeof(configex));

	configex.src_para.mem_type = CANVAS_ALLOC;	//CANVAS_OSD0
	configex.src_para.left = 0;
	configex.src_para.top = 0;
	configex.src_para.width = var_info.xres;
	configex.src_para.height = var_info.yres;
	configex.src_para.x_rev = revX;
	configex.src_para.y_rev = revY;
	configex.src_planes[0].addr = srcParam.physical_address;
	configex.src_planes[0].w = configex.src_para.width;
	configex.src_planes[0].h = configex.src_para.height;
	configex.src_para.format = GE2D_FORMAT_S32_ARGB; // GE2D_FORMAT_S32_BGRA; // GE2D_FMT_S32_RGBA;


	configex.src2_para.mem_type = CANVAS_TYPE_INVALID;


	configex.dst_para.mem_type = CANVAS_ALLOC; // CANVAS_OSD0;
	configex.dst_para.left = 0;
	configex.dst_para.top = 0;
	configex.dst_para.width = configex.src_para.width;
	configex.dst_para.height = configex.src_para.height;
	configex.dst_para.x_rev = configex.src_para.x_rev;
	configex.dst_para.y_rev = configex.src_para.y_rev;
	configex.dst_planes[0].addr = dstParam.physical_address;
	configex.dst_planes[0].w = configex.dst_para.width;
	configex.dst_planes[0].h = configex.dst_para.height;
	configex.dst_para.format = GE2D_FORMAT_S32_ARGB;


	ret = ioctl(ge2d_fd, GE2D_CONFIG_EX, &configex);
	if (ret < 0)
	{
		ERROR_STR("GE2D_CONFIG_EX failed.\n");
	}

	// Perform the blit operation
	struct ge2d_para_s blitRect;
	memset(&blitRect, 0, sizeof(blitRect));

	blitRect.src1_rect.x = srcX;
	blitRect.src1_rect.y = srcY;
	blitRect.src1_rect.w = width;
	blitRect.src1_rect.h = height;
	blitRect.dst_rect.x = dstX;
	blitRect.dst_rect.y = dstY;

	if (revY) // && height > 1
	{
		blitRect.src1_rect.y -= 1;
	}

	ret = ioctl(ge2d_fd, GE2D_BLIT, &blitRect);
	if (ret < 0)
	{
		ERROR_STR("GE2D_BLIT failed.\n");
	}


	ret = ioctl(memclient_fd, MEMCLIENT_RELEASE_UMP, dstID);
	if (ret < 0)
	{
		ERROR_STR("dstID MEMCLIENT_RELEASE_UMP failed.\n");
	}

	ret = ioctl(memclient_fd, MEMCLIENT_RELEASE_UMP, srcID);
	if (ret < 0)
	{
		ERROR_STR("srcID MEMCLIENT_RELEASE_UMP failed.\n");
	}

}
static Bool maliModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData)
{
	unsigned int size;
	PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPixmap);
	mali_mem_info *mem_info;
	ScreenPtr pScreen = pPixmap->drawable.pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	if (!pPixmap)
	{
		return FALSE;
	}

	miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData);

	if ((pPixData == fPtr->fbmem) || offset)
	{
		/* Wrap one of the fbdev virtual buffers */
		ump_secure_id ump_id = UMP_INVALID_SECURE_ID;

		privPixmap->isFrameBuffer = TRUE;

		mem_info = privPixmap->mem_info;

		if (mem_info)
		{
			return TRUE;
		}

		/* create new mem_info for the on-screen buffer */
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate for memory metadata");
			return FALSE;
		}

		/* get the secure ID for the framebuffers */
		if (!offset)
		{
			(void)ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF1, &ump_id);
			ERROR_MSG("GET_UMP_SECURE_ID_BUF1 returned 0x%x offset: %i virt address: %p fb_virt: %p\n", ump_id, offset, pPixData, fPtr->fbmem);
		}
		else
		{
			(void)ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF2, &ump_id);
			ERROR_MSG("GET_UMP_SECURE_ID_BUF2 returned 0x%x offset: %i virt address: %p fb_virt: %p\n", ump_id, offset, pPixData, fPtr->fbmem);
		}

		if (UMP_INVALID_SECURE_ID == ump_id)
		{
			free(mem_info);
			privPixmap->mem_info = NULL;
			ERROR_MSG("UMP failed to retrieve secure id");
			return FALSE;
		}

		mem_info->handle = ump_handle_create_from_secure_id(ump_id);

		if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
		{
			ERROR_MSG("UMP failed to create handle from secure id");
			free(mem_info);
			privPixmap->mem_info = NULL;
			return FALSE;
		}

		size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;
		mem_info->usize = size;

		privPixmap->mem_info = mem_info;

		if (bitsPerPixel != 0)
		{
			privPixmap->bits_per_pixel = bitsPerPixel;
		}

		/* When this is called directly from X to create the front buffer, offset is zero as expected. When this
		 * function is called recursively to create the back buffer, offset is the offset within the fbdev to
		 * the second buffer */
		privPixmap->mem_info->offset = offset;

		/* Only wrap the other half if there is another half! */
		if (pPixData == fPtr->fbmem)
		{
			/* This is executed only when this function is called directly from X. We need to create the
			 * back buffer now because we can't "wrap" existing memory in a pixmap during DRI2CreateBuffer
			 * for the back buffer of the framebuffer. In DRI2CreateBuffer instead of allocating a new
			 * pixmap for the back buffer like we do for non-swappable windows, we'll just grab this pointer
			 * from the screen pixmap and return it. */

			PrivPixmap *other_privPixmap;

			offset = size;
			privPixmap->other_buffer = (*pScreen->CreatePixmap)(pScreen, width, height, depth, 0);

			/* Store a pointer to this pixmap in the one we just created. Both fbdev pixmaps are then
			 * accessible from the screen pixmap, whichever of the fbdev pixmaps happens to be the screen
			 * pixmap at the time */
			other_privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(privPixmap->other_buffer);
			other_privPixmap->other_buffer = pPixmap;

			offset = 0;
		}

		INFO_MSG("Creating FRAMEBUFFER pixmap %p at offset %lu, privPixmap=%p\n", pPixmap, privPixmap->mem_info->offset, privPixmap);

		return TRUE;
	}

	if (pPixData)
	{
		/* When this happens we're being told to wrap existing pixmap data for which we don't know the UMP
		 * handle. We can and still need to wrap it but it won't be offscreen - we can't accelerate it in any
		 * way. */

		if (privPixmap->mem_info != NULL)
		{
			return TRUE;
		}

		return FALSE;
	}

	pPixmap->devKind = ((pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel) + 7) / 8;
	pPixmap->devKind = MALI_ALIGN(pPixmap->devKind, 8);

	size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;

	/* allocate pixmap data */
	mem_info = privPixmap->mem_info;

	if (mem_info && mem_info->usize == size)
	{
		return TRUE;
	}

	if (mem_info && mem_info->usize != 0)
	{
		ump_reference_release(mem_info->handle);
		mem_info->handle = NULL;
		memset(privPixmap, 0, sizeof(*privPixmap));

		return TRUE;
	}

	if (!size)
	{
		return TRUE;
	}

	if (NULL == mem_info)
	{
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate memory metadata");
			return FALSE;
		}
	}

	if (fPtr->use_cached_ump)
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR | UMP_REF_DRV_CONSTRAINT_USE_CACHE);
	}
	else
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR);
	}

	if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
	{
		ERROR_MSG("failed to allocate UMP memory (%i bytes)", size);
		return FALSE;
	}

	mem_info->usize = size;
	privPixmap->mem_info = mem_info;
	privPixmap->mem_info->usize = size;
	privPixmap->bits_per_pixel = 16;

	return TRUE;
}