forked from KolibriOS/kolibrios
3287cff0b2
git-svn-id: svn://kolibrios.org@5371 a494cfbc-eb01-0410-851d-a64ba20cac60
265 lines
5.7 KiB
C
265 lines
5.7 KiB
C
#include <stdio.h>
|
|
#include <malloc.h>
|
|
#include <stdbool.h>
|
|
#include <kos32sys.h>
|
|
|
|
#include "pixlib3.h"
|
|
#include "pixdriver.h"
|
|
|
|
#define DISPLAY_VERSION 0x0200 /* 2.00 */
|
|
|
|
#define SRV_GETVERSION 0
|
|
#define SRV_GET_CAPS 3
|
|
|
|
|
|
#define BUFFER_SIZE(n) ((n)*sizeof(uint32_t))
|
|
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
|
|
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
|
|
|
|
struct bitmap
|
|
{
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint32_t pitch;
|
|
void *buffer;
|
|
uint32_t size;
|
|
};
|
|
|
|
static uint32_t fd;
|
|
static struct pix_driver *driver;
|
|
|
|
|
|
static bitmap_t *sw_create_bitmap(uint32_t width, uint32_t height)
|
|
{
|
|
bitmap_t *bitmap;
|
|
|
|
bitmap = malloc(sizeof(bitmap_t));
|
|
if(bitmap == NULL)
|
|
goto err_0;
|
|
|
|
bitmap->width = width;
|
|
bitmap->height = height;
|
|
|
|
bitmap->pitch = ALIGN(width * 4, 16);
|
|
bitmap->size = ALIGN(bitmap->pitch * height, 4096);
|
|
|
|
bitmap->buffer = user_alloc(bitmap->size);
|
|
if (bitmap->buffer == NULL)
|
|
goto err_1;
|
|
|
|
printf("create bitmap: %p %dx%d buffer: %p\n",
|
|
bitmap, bitmap->width, bitmap->height, bitmap->buffer);
|
|
|
|
return bitmap;
|
|
|
|
err_1:
|
|
free(bitmap);
|
|
err_0:
|
|
return NULL;
|
|
};
|
|
|
|
static int sw_destroy_bitmap(bitmap_t * bitmap)
|
|
{
|
|
user_free(bitmap->buffer);
|
|
free(bitmap);
|
|
return 0;
|
|
};
|
|
|
|
static void *sw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch)
|
|
{
|
|
*pitch = bitmap->pitch;
|
|
|
|
return bitmap->buffer;
|
|
};
|
|
|
|
static int sw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height)
|
|
{
|
|
uint32_t size;
|
|
uint32_t pitch;
|
|
|
|
pitch = ALIGN(width * 4, 16);
|
|
size = ALIGN(pitch * height, 4096);
|
|
|
|
if (size > bitmap->size)
|
|
{
|
|
bitmap->buffer = user_realloc(bitmap->buffer, size); /* grow buffer */
|
|
if (bitmap->buffer == NULL)
|
|
return -1;
|
|
|
|
bitmap->size = size;
|
|
}
|
|
else if (size < bitmap->size)
|
|
user_unmap(bitmap->buffer, size, bitmap->size - size); /* unmap unused pages */
|
|
|
|
bitmap->width = width;
|
|
bitmap->height = height;
|
|
bitmap->pitch = pitch;
|
|
|
|
return 0;
|
|
};
|
|
|
|
static int sw_blit(bitmap_t * bitmap, int dst_x, int dst_y,
|
|
uint32_t w, uint32_t h, int src_x, int src_y)
|
|
{
|
|
struct blit_call bc;
|
|
int ret;
|
|
|
|
bc.dstx = dst_x;
|
|
bc.dsty = dst_y;
|
|
bc.w = w;
|
|
bc.h = h;
|
|
bc.srcx = src_x;
|
|
bc.srcy = src_y;
|
|
bc.srcw = bitmap->width;
|
|
bc.srch = bitmap->height;
|
|
bc.stride = bitmap->pitch;
|
|
bc.bitmap = bitmap->buffer;
|
|
|
|
__asm__ __volatile__(
|
|
"int $0x40":"=a"(ret):"a"(73), "b"(0x00),
|
|
"c"(&bc):"memory");
|
|
|
|
return ret;
|
|
};
|
|
|
|
static int sw_create_client(int x, int y, uint32_t width, uint32_t height)
|
|
{
|
|
return 0;
|
|
};
|
|
|
|
static int sw_resize_client(int x, int y, uint32_t width, uint32_t height)
|
|
{
|
|
return 0;
|
|
};
|
|
|
|
bitmap_t *pxCreateBitmap(uint32_t width, uint32_t height)
|
|
{
|
|
return driver->create_bitmap(width, height);
|
|
};
|
|
|
|
int pxDestroyBitmap(bitmap_t *bitmap)
|
|
{
|
|
return driver->destroy_bitmap(bitmap);
|
|
};
|
|
|
|
void *pxLockBitmap(bitmap_t *bitmap, uint32_t *pitch)
|
|
{
|
|
return driver->lock_bitmap(bitmap, pitch);
|
|
};
|
|
|
|
int pxResizeBitmap(bitmap_t *bitmap, uint32_t width, uint32_t height)
|
|
{
|
|
return driver->resize_bitmap(bitmap, width, height);
|
|
};
|
|
|
|
int pxBlitBitmap(bitmap_t *bitmap, int dst_x, int dst_y,
|
|
uint32_t w, uint32_t h, int src_x, int src_y)
|
|
{
|
|
return driver->blit_bitmap(bitmap, dst_x, dst_y,
|
|
w, h, src_x, src_y);
|
|
};
|
|
|
|
int pxCreateClient(int x, int y, uint32_t width, uint32_t height)
|
|
{
|
|
return driver->create_client(x, y, width, height);
|
|
}
|
|
|
|
int pxResizeClient(int x, int y, uint32_t width, uint32_t height)
|
|
{
|
|
printf("resize client\n");
|
|
return driver->resize_client(x, y, width, height);
|
|
}
|
|
|
|
static struct pix_driver sw_driver =
|
|
{
|
|
0,
|
|
sw_create_bitmap,
|
|
sw_destroy_bitmap,
|
|
sw_lock_bitmap,
|
|
sw_resize_bitmap,
|
|
sw_blit,
|
|
sw_create_client,
|
|
sw_resize_client,
|
|
NULL
|
|
};
|
|
|
|
|
|
uint32_t pxInit(int hw)
|
|
{
|
|
void *lib;
|
|
struct pix_driver *(*drventry)(uint32_t service);
|
|
|
|
uint32_t api_version;
|
|
ioctl_t io;
|
|
|
|
driver = &sw_driver;
|
|
|
|
if(hw == 0)
|
|
return 0;
|
|
|
|
if (fd != 0)
|
|
return driver->driver_caps;
|
|
|
|
fd = get_service("DISPLAY");
|
|
if (fd == 0)
|
|
goto fail;
|
|
|
|
io.handle = fd;
|
|
io.io_code = SRV_GETVERSION;
|
|
io.input = NULL;
|
|
io.inp_size = 0;
|
|
io.output = &api_version;
|
|
io.out_size = BUFFER_SIZE(1);
|
|
|
|
if (call_service(&io) != 0)
|
|
goto fail;
|
|
|
|
if ((DISPLAY_VERSION > (api_version & 0xFFFF)) ||
|
|
(DISPLAY_VERSION < (api_version >> 16)))
|
|
goto fail;
|
|
|
|
lib = load_library("pixlib-gl.dll");
|
|
if(lib == 0)
|
|
goto fail;
|
|
|
|
drventry = get_proc_address(lib, "DrvInit");
|
|
|
|
if( drventry == NULL)
|
|
goto fail;
|
|
|
|
driver = drventry(fd);
|
|
if(driver == NULL)
|
|
{
|
|
driver = &sw_driver;
|
|
goto fail;
|
|
};
|
|
|
|
if (driver->driver_caps)
|
|
printf("2D caps %s%s%s\n",
|
|
(driver->driver_caps & HW_BIT_BLIT) != 0 ? "HW_BIT_BLIT " : "",
|
|
(driver->driver_caps & HW_TEX_BLIT) != 0 ? "HW_TEX_BLIT " : "",
|
|
(driver->driver_caps & HW_VID_BLIT) != 0 ? "HW_VID_BLIT " : "");
|
|
|
|
return driver->driver_caps;
|
|
|
|
fail:
|
|
printf("Warning! Hardware initialization failed.\n"
|
|
"fallback to software rendering.\n");
|
|
fd = 0;
|
|
return 0;
|
|
};
|
|
|
|
void pxFini()
|
|
{
|
|
if (driver->fini)
|
|
driver->fini();
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|