brender-1997/myst/Devpixmp.c
2022-05-03 14:31:40 -07:00

1119 lines
27 KiB
C

/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* Device pixelmap methods
*/
#include <stddef.h>
#include <string.h>
#include "drv.h"
#include "pm.h"
#include "host.h"
#include "shortcut.h"
#include "brassert.h"
#define MSI_LFB_DISABLE ((T_msiParameters*) -1)
br_error MystiqueAllocateSysMemPixelmap(br_device_pixelmap *self, br_device_pixelmap **newpm, int w, int h);
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, copyTo)(struct br_device_pixelmap *self, br_device_pixelmap *src);
/*
* Default dispatch table for device pixelmap (defined at end of file)
*/
static struct br_device_pixelmap_dispatch devicePixelmapDispatch;
/*
* Device pixelmap info. template
*/
#define F(f) offsetof(struct br_device_pixelmap, f)
static struct br_tv_template_entry devicePixelmapTemplateEntries[] = {
{BRT_WIDTH_I32, 0, F(pm_width), BRTV_QUERY | BRTV_ALL, BRTV_CONV_I32_U16, },
{BRT_HEIGHT_I32, 0, F(pm_height), BRTV_QUERY | BRTV_ALL, BRTV_CONV_I32_U16, },
{BRT_PIXEL_TYPE_U8, 0, F(pm_type), BRTV_QUERY | BRTV_ALL, BRTV_CONV_I32_U8, },
{BRT_OUTPUT_FACILITY_O, 0, F(output_facility), BRTV_QUERY | BRTV_ALL, BRTV_CONV_COPY, },
{BRT_FACILITY_O, 0, F(output_facility), BRTV_QUERY, BRTV_CONV_COPY, },
{BRT_IDENTIFIER_CSTR, 0, F(pm_identifier), BRTV_QUERY | BRTV_ALL, BRTV_CONV_COPY, },
{BRT_CLUT_O, 0, F(clut), BRTV_QUERY | BRTV_ALL, BRTV_CONV_COPY, },
};
#undef F
static struct br_tv_template devicePixelmapTemplate = {
BR_ASIZE(devicePixelmapTemplateEntries),
devicePixelmapTemplateEntries
};
#ifdef _WIN32
/*
* Structures used to translate tokens and values
*/
struct hwnd_tokens {
HWND hwnd;
};
#define F(f) offsetof(struct hwnd_tokens, f)
static struct br_tv_template_entry hwndTemplateEntries[] = {
{BRT(WINDOW_HANDLE_H), F(hwnd), BRTV_SET, BRTV_CONV_COPY, },
};
#undef F
static struct br_tv_template hwndTemplate = {
BR_ASIZE(hwndTemplateEntries),
hwndTemplateEntries
};
#endif
/*
* Structure used to unpack the 'match' tokens/values
*/
struct match_tokens {
br_token use;
br_int_32 pixel_bits;
br_int_32 width;
br_int_32 height;
br_object *renderer;
};
#define F(f) offsetof(struct match_tokens, f)
static struct br_tv_template_entry matchTemplateEntries[] = {
{BRT_USE_T, 0, F(use), BRTV_SET, BRTV_CONV_COPY, },
{BRT_PIXEL_BITS_I32, 0, F(pixel_bits), BRTV_SET, BRTV_CONV_COPY, },
{BRT_RENDERER_O, 0, F(renderer), BRTV_SET, BRTV_CONV_COPY, },
{BRT_WIDTH_I32, 0, F(width), BRTV_SET, BRTV_CONV_COPY, },
{BRT_HEIGHT_I32, 0, F(height), BRTV_SET, BRTV_CONV_COPY, },
};
#undef F
static struct br_tv_template matchTemplate = {
BR_ASIZE(matchTemplateEntries),
matchTemplateEntries
};
#define HWND_INTERFACE
#ifdef _WIN32
#ifndef HWND_INTERFACE
/*
* For the Mystique's slightly noddy interface, create a driver window class
* and front-window which passes all its messages down to the application window
*/
HWND local_window_handle, application_hwnd;
LRESULT CALLBACK MystiqueWindowProc(HWND hwnd, unsigned msg,
UINT wParam, LONG lParam )
{
/* Kick message down to the application */
SendMessage(application_hwnd, msg, wParam, lParam);
return( DefWindowProc( hwnd, msg, wParam, lParam ) );
}
char MystiqueDeviceClass[64]="MBRDevClass";
br_error MystiqueWindowSetup(HWND hWnd)
{
WNDCLASS wc;
HANDLE instance;
application_hwnd = hWnd;
instance = GetModuleHandle(NULL);//(HANDLE) GetWindowLong(hWnd, GWL_HINSTANCE);
/*
* set up and register window class
*/
wc.style = 0;
wc.lpfnWndProc = MystiqueWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = MystiqueDeviceClass;
if (!RegisterClass(&wc))
return(BRE_DEV_FAIL);
local_window_handle = CreateWindowEx(
0,
MystiqueDeviceClass,
"Mystique Device Driver",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,
300,
NULL,
NULL,
instance,
NULL
);
if (!local_window_handle)
return(BRE_DEV_FAIL);
return(BRE_OK);
}
#endif // HWND_INTERFACE
#endif // _WIN32
T_msiInfo *msiInfo;
/*
* Create a new device pixelmap and set a display mode
*/
br_error DevicePixelmapMystAllocateMode(br_device *dev, br_output_facility *facility,
br_device_pixelmap **newpm, br_token_value *tv)
{
br_device_pixelmap *self;
br_uint_32 w, h;
br_uint_16 qual;
syslog("DevicePixelmapMystAllocateMode: Allocating front buffer");
if (dev->active_buffers[BT_FRONTSCREEN])
return(BRE_DEV_ALREADY_INIT);
CLEAR_TEMPLATE(devicePixelmap);
CLEAR_TEMPLATE(match);
w = facility->width;
h = facility->height;
#ifdef _WIN32
{
struct hwnd_tokens ht;
br_int_32 count;
// br_error result;
/* Parse for hwnd */
CLEAR_TEMPLATE(hwnd);
ht.hwnd = NULL;
hwndTemplate.res = DeviceMystResource(dev);
BrTokenValueSetMany(&ht, &count, NULL, tv, &hwndTemplate);
#ifdef HWND_INTERFACE
dev->msiInfo = msiInit(w, h, facility->colour_bits, TRUE, FALSE, ht.hwnd);
#else // HWND_INTERFACE
result = MystiqueWindowSetup(ht.hwnd);
if (result != BRE_OK)
return(result);
/* Start up MSI, 16 bpp, with Z-buffer, debug info */
dev->msiInfo = msiInit(w, h, facility->colour_bits, TRUE, TRUE, MystiqueWindowProc);
#endif // HWND_INTERFACE
}
#else
syslog(" -> Starting MSI");
/* Start up MSI, 16 bpp, with Z-buffer, debug info */
dev->msiInfo = msiInit(w, h, facility->colour_bits, TRUE, TRUE);
#endif
msiInfo = dev->msiInfo;
if (!dev->msiInfo)
return(BRE_DEV_HARDWARE_SET);
syslog(" -> MSI up OK");
self = BrResAllocate(DeviceMystResource(dev), sizeof(*self), BR_MEMORY_OBJECT);
if (!self)
return(BRE_DEV_NO_MEMORY);
self->dispatch = &devicePixelmapDispatch;
self->pm_identifier = ObjectIdentifier(facility);
self->pm_pixels = 0;
HostSelectorDS(&qual);
self->pm_pixels_qualifier = qual;
self->pm_type = (br_uint_8) OutputFacilityMystType(facility);
self->pm_width = (br_uint_16) w;
self->pm_height = (br_uint_16) h;
self->pm_row_bytes = 0;
self->pm_origin_x = 0;
self->pm_origin_y = 0;
self->pm_flags = BR_PMF_NO_ACCESS;
self->pm_base_x = 0;
self->pm_base_y = 0;
self->output_facility = facility;
self->clut = dev->clut;
self->buffer_type = BT_FRONTSCREEN;
dev->active_buffers[BT_FRONTSCREEN] = self;
ObjectContainerAddFront(facility, (br_object *)self);
syslog(" -> complete");
*newpm = self;
return(BRE_OK);
}
static void BR_CMETHOD_DECL(br_device_pixelmap_mystique, free)(br_device_pixelmap *self)
{
if (self->buffer_type == BT_FRONTSCREEN) {
/* Clear out texture heaps */
ClearHeap();
/* Restore and shutdown: should probably check that back buffer
* has already gone */
ObjectContainerRemove(self->output_facility, (br_object *)self);
self->output_facility->num_instances--;
ObjectDevice(self)->active_buffers[self->buffer_type] = NULL;
msiExit();
}
/*
* Free up pixelmap structure
*/
BrResFreeNoCallback(self);
}
br_token BR_CMETHOD_DECL(br_device_pixelmap_mystique, type)(br_device_pixelmap *self)
{
return BRT_DEVICE_PIXELMAP;
}
br_boolean BR_CMETHOD_DECL(br_device_pixelmap_mystique, isType)(br_device_pixelmap *self, br_token t)
{
return (t == BRT_DEVICE_PIXELMAP) || (t == BRT_OBJECT);
}
br_int_32 BR_CMETHOD_DECL(br_device_pixelmap_mystique, space)(br_device_pixelmap *self)
{
return sizeof(br_device_pixelmap);
}
struct br_tv_template * BR_CMETHOD_DECL(br_device_pixelmap_mystique,queryTemplate)
(br_device_pixelmap *self)
{
devicePixelmapTemplate.res = DeviceMystResource(ObjectMystDevice(self));
return &devicePixelmapTemplate;
}
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, flush)(
struct br_device_pixelmap *self)
{
return BRE_OK;
}
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, synchronise)(
struct br_device_pixelmap *self,
br_token sync_type,
br_boolean block)
{
return BRE_OK;
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, match)(br_device_pixelmap *self,
br_device_pixelmap **newpm, br_token_value *tv)
{
struct match_tokens mt = {BRT_NONE, 0};
br_int_32 count;
br_device_pixelmap *pm;
br_device *dev = ObjectDevice(self);
br_uint_16 qual;
syslog("Pixelmap Match");
matchTemplate.res = DeviceMystResource(dev);
/*
* Default width and height
*/
mt.width = self->pm_width;
mt.height = self->pm_height;
BrTokenValueSetMany(&mt, &count, NULL, tv, &matchTemplate);
/*
* Create the pixelmap structure
*/
if(mt.use == BRT_OFFSCREEN) {
syslog(" -> offscreen match");
/*
* Check that the source buffer is of the correct type
*/
if(self->buffer_type != BT_FRONTSCREEN)
return BRE_DEV_UNSUPPORTED;
if(dev->active_buffers[BT_BACKSCREEN]) {
// return BRE_DEV_ALREADY_INIT;
/* OK we've already allocated the backscreen - now we have the hack */
return(MystiqueAllocateSysMemPixelmap(self, newpm, mt.width, mt.height));
}
/*
* Create an offscreen buffer pixelmap
*/
pm = BrResAllocate(DeviceMystResource(dev),sizeof(*pm), BR_MEMORY_OBJECT);
pm->pm_width = self->pm_width;
pm->pm_height = self->pm_height;
pm->pm_pixels = 0;
HostSelectorDS(&qual);
self->pm_pixels_qualifier = qual;
pm->pm_origin_x = self->pm_origin_x;
pm->pm_origin_y = self->pm_origin_y;
pm->pm_flags = BR_PMF_NO_ACCESS;
pm->output_facility = self->output_facility;
pm->pm_type = self->pm_type;
pm->dispatch = &devicePixelmapDispatch;
pm->pm_identifier = "Offscreen";
pm->buffer_type = BT_BACKSCREEN;
dev->active_buffers[BT_BACKSCREEN] = pm;
self->offscreen = pm;
} else if(mt.use == BRT_DEPTH) {
syslog(" -> depth match");
/*
* Check that the source buffer is of the correct type
*/
if(self->buffer_type != BT_FRONTSCREEN &&
self->buffer_type != BT_BACKSCREEN)
return BRE_DEV_UNSUPPORTED;
if(dev->active_buffers[BT_DEPTH])
return BRE_DEV_ALREADY_INIT;
/*
* Create an depth buffer pixelmap
*/
pm = BrResAllocate(DeviceMystResource(dev),sizeof(*pm), BR_MEMORY_OBJECT);
if (!pm)
return(BRE_DEV_NO_MEMORY);
pm->pm_width = self->pm_width;
pm->pm_height = self->pm_height;
pm->pm_pixels = 0;
HostSelectorDS(&qual);
self->pm_pixels_qualifier = qual;
pm->pm_origin_x = self->pm_origin_x;
pm->pm_origin_y = self->pm_origin_y;
pm->pm_flags = BR_PMF_NO_ACCESS;
pm->output_facility = self->output_facility;
pm->pm_type = BR_PMT_DEPTH_16;
pm->dispatch = &devicePixelmapDispatch;
pm->pm_identifier = "Depth";
pm->buffer_type = BT_DEPTH;
dev->active_buffers[BT_DEPTH] = pm;
self->depth = pm;
} else if (mt.use == BRT_NO_RENDER) {
/* No render pixelmaps require a device system memory pixelmap */
return(MystiqueAllocateSysMemPixelmap(self, newpm, mt.width, mt.height));
} else {
return BRE_DEV_UNSUPPORTED;
}
syslog(" -> complete");
*newpm = pm;
return BRE_OK;
}
/*
* Because of the limited availabilty of the Mystique's pixelmap fills,
* have to buffer them and do them here
*
* This start function is called from anywhere by which point the frame must
* definitely have started; that is, at the first renderbegin block or
* at the double buffer call (cos that requires EndFrame)
*/
br_boolean frame_started = BR_FALSE;
BOOL mystique_rgb_fill = FALSE;
br_colour mystique_rgb_fill_colour;
BOOL mystique_z_fill = FALSE;
float mystique_z_fill_value;
void MystiqueBuffersStartFrame(void)
{
if (!frame_started) {
syslog("BuffersStartFrame");
msiStartFrame(mystique_rgb_fill,
(float) BR_RED(mystique_rgb_fill_colour),
(float) BR_GRN(mystique_rgb_fill_colour),
(float) BR_BLU(mystique_rgb_fill_colour),
mystique_z_fill,
mystique_z_fill_value);
frame_started = BR_TRUE;
mystique_rgb_fill = FALSE;
mystique_z_fill = FALSE;
syslog(" -> complete");
}
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, doubleBuffer)(br_device_pixelmap *self, br_device_pixelmap *src)
{
/*
* fail if doubleBuffer is not invoked on front/back pair
*/
if(self != ObjectDevice(self)->active_buffers[BT_FRONTSCREEN] ||
src != ObjectDevice(self)->active_buffers[BT_BACKSCREEN])
return BRE_DEV_UNSUPPORTED;
MystiqueBuffersStartFrame();
syslog("DoubleBuffer");
/*
* Do the flip... wait for it to be ready.
* Setting wait to FALSE may well be possible here.
*/
msiEndFrame(FALSE, 0, TRUE);
/* Clear out the startframe stuff */
frame_started = BR_FALSE;
mystique_rgb_fill = FALSE;
mystique_z_fill = FALSE;
syslog(" -> complete");
// Temporary hack
mystique_rgb_fill = TRUE;
mystique_z_fill = TRUE;
return BRE_OK;
}
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, allocateSub)\
(br_device_pixelmap *self, br_device_pixelmap **newpm, br_rectangle *rect)
{
br_device_pixelmap *pm;
br_rectangle out;
// If the parent is null then ooops!
if(!self)
return(BRE_FAIL);
/*
* Create the new structure and copy
*/
pm = BrResAllocate(DeviceMystResource(ObjectMystDevice(self)),sizeof(*pm),BR_MEMORY_PIXELMAP);
if (!pm)
return(BRE_DEV_NO_MEMORY);
// Set all the fields to be the same as the parent pixelmap for now
*pm = *self;
/*
* Pixel rows are not contiguous
*/
pm->pm_flags &= ~BR_PMF_LINEAR;
/*
* Create sub-window (clipped against original)
*/
if(PixelmapRectangleClip(&out, rect, (br_pixelmap *)self) == BR_CLIP_REJECT)
return BRE_FAIL;
pm->pm_base_x += out.x;
pm->pm_base_y += out.y;
pm->pm_width = out.w;
pm->pm_height = out.h;
pm->pm_origin_x = 0;
pm->pm_origin_y = 0;
*newpm = (br_device_pixelmap *)pm;
return BRE_OK;
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, rectangleFill)
(br_device_pixelmap *self, br_rectangle *rect, br_uint_32 colour)
{
br_uint_16 *dptr, *dp;
br_int_32 i, j, w, h;
br_uint_32 col;
br_rectangle arect;
br_boolean end;
if(self != ObjectDevice(self)->active_buffers[BT_BACKSCREEN])
return(BRE_DEV_UNSUPPORTED);
if(PixelmapRectangleClip(&arect, rect, (br_pixelmap *)self) == BR_CLIP_REJECT)
return BRE_OK;
MystiqueBuffersStartFrame();
msiSetParameters(NULL);
dptr = ((br_uint_16 *) msiInfo->msiColor.pMem) +
(arect.x+self->pm_base_x) +
((arect.y+self->pm_base_y) * (msiInfo->msiColor.Pitch/2));
w = arect.w;
#if _WIN32
if (w&1) end = BR_TRUE;
else end = BR_FALSE;
w >>= 1; // dword moves
col = colour + (colour<<16);
#endif
h = arect.h;
for(j=0; j<h; j++) {
dp = dptr;
#if _WIN32
if (end) *dp++ = (br_uint_16) colour;
_asm {
mov ecx, w
mov edi, dp
mov eax, col
cld
rep stosd
}
#else
for(i=0; i<w; i++)
*dp++ = colour;
#endif
dptr += (msiInfo->msiColor.Pitch/2);
}
msiSetParameters(MSI_LFB_DISABLE);
return BRE_OK;
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, fill)(br_device_pixelmap *self, br_uint_32 colour)
{
syslog("Fill");
/* This is problematic. The fastest way under MSI to clear is to
* use StartFrame, but this is not guaranteed to be correct with
* 2D operations, plus Z and colour clears must be specified
* simulataneously. */
if ((self->pm_base_x != 0) || (self->pm_base_y != 0)) {
br_rectangle rect;
rect.x = - self->pm_origin_x;
rect.y = - self->pm_origin_y;
rect.w = self->pm_width;
rect.h = self->pm_height;
return(BR_CMETHOD(br_device_pixelmap_mystique, rectangleFill)(self, &rect, colour));
}
if(self == ObjectDevice(self)->active_buffers[BT_FRONTSCREEN])
return(BRE_DEV_UNSUPPORTED);
if(self == ObjectDevice(self)->active_buffers[BT_BACKSCREEN]) {
if (!frame_started) {
mystique_rgb_fill = TRUE;
switch (self->pm_type) {
case BR_PMT_RGB_555:
mystique_rgb_fill_colour = BR_COLOUR_RGB(
(colour >> 7) & 0xf8 | (colour >> 12) & 0x07,
(colour >> 2) & 0xf8 | (colour >> 7) & 0x07,
(colour << 3) & 0xf8 | (colour >> 2) & 0x07);
break;
case BR_PMT_RGB_565:
mystique_rgb_fill_colour = BR_COLOUR_RGB(
(colour >> 8) & 0xf8 | (colour >> 13) & 0x07,
(colour >> 3) & 0xfc | (colour >> 9) & 0x03,
(colour << 3) & 0xf8 | (colour >> 2) & 0x07);
break;
case BR_PMT_RGB_888:
mystique_rgb_fill_colour = colour;
break;
default:
mystique_rgb_fill_colour = 0; // shrug!
break;
}
} else {
/* Fill manually */
}
}
if(self == ObjectDevice(self)->active_buffers[BT_DEPTH]) {
if (!frame_started) {
mystique_z_fill = TRUE;
mystique_z_fill_value = ((float) colour / (float) 0xffffffff);
} else {
/* Fill manually */
}
}
syslog(" -> complete");
return BRE_OK;
}
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, copy)(br_device_pixelmap *self, br_device_pixelmap *src)
{
if (src->buffer_type == BT_SYSMEM)
return BR_CMETHOD(br_device_pixelmap_mystique, copyTo)(self, src);
return(BRE_DEV_UNSUPPORTED);
}
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, copyTo)(struct br_device_pixelmap *self, br_device_pixelmap *src)
{
br_uint_16 *dptr, *d;
br_uint_16 *sptr, *s;
br_int_32 i, j, w, h;
br_boolean end;
if ((self->pm_width != src->pm_width) || (self->pm_height != src->pm_height))
return(BRE_DEV_FAIL);
if (src->pm_type != BR_PMT_RGB_565)
return(BRE_DEV_UNSUPPORTED);
if(self != ObjectDevice(self)->active_buffers[BT_BACKSCREEN])
return(BRE_DEV_UNSUPPORTED);
MystiqueBuffersStartFrame();
msiSetParameters(NULL);
dptr = ((br_uint_16 *) msiInfo->msiColor.pMem) +
self->pm_base_x +
(self->pm_base_y * (msiInfo->msiColor.Pitch/2));
sptr = src->pm_pixels;
w = src->pm_width;
#if _WIN32
if (w&1) end = BR_TRUE;
else end = BR_FALSE;
w >>= 1; // dword moves
#endif
h = src->pm_height;
for(j=0; j<h; j++) {
d = dptr;
s = sptr;
#if _WIN32
if (end) *d++ = *s++;
_asm {
mov ecx, w
mov esi, s
mov edi, d
cld
rep movsd
}
#else
for(i=0; i<w; i++)
*d++ = *s++;
#endif
dptr += (msiInfo->msiColor.Pitch/2);
sptr += (src->pm_row_bytes/2);
}
msiSetParameters(MSI_LFB_DISABLE);
return(BRE_OK);
}
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, copyFrom)(struct br_device_pixelmap *self, br_device_pixelmap *src)
{
return(BRE_DEV_UNSUPPORTED);
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, rectangleCopyTo)
(br_device_pixelmap *self, br_point *p, br_device_pixelmap *src, br_rectangle *r)
{
br_uint_16 *dptr, *sptr, *dp, *sp;
br_rectangle ar;
br_point ap;
br_int_32 i, j, w, h;
if(self != ObjectDevice(self)->active_buffers[BT_BACKSCREEN])
return(BRE_DEV_UNSUPPORTED);
if(PixelmapRectangleClipTwo(&ar, &ap, r, p, (br_pixelmap *)self, (br_pixelmap *)src) == BR_CLIP_REJECT)
return BRE_OK;
MystiqueBuffersStartFrame();
msiSetParameters(NULL);
dptr = ((br_uint_16 *) msiInfo->msiColor.pMem) +
(ap.x+self->pm_base_x) +
((ap.y+self->pm_base_y) * (msiInfo->msiColor.Pitch/2));
sptr = ((br_uint_16 *) src->pm_pixels) + ar.x + (ar.y * src->pm_row_bytes / 2);
w = ar.w;
#if _WIN32
w >>= 1; // dword moves
#endif
h = ar.h;
for(j=0; j<h; j++) {
#if _WIN32
_asm {
mov ecx, w
mov esi, sptr
mov edi, dptr
cld
rep movsd
}
#else
dp = dptr;
sp = sptr;
for(i=0; i<w; i++)
*dp++ = *sp++;
#endif
dptr += (msiInfo->msiColor.Pitch/2);
sptr += (src->pm_row_bytes/2);
}
msiSetParameters(MSI_LFB_DISABLE);
return BRE_OK;
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, rectangleCopyFrom)
(br_device_pixelmap *self, br_point *p, br_device_pixelmap *mem, br_rectangle *r)
{
return BRE_DEV_UNSUPPORTED;
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, pixelSet)
(br_device_pixelmap *self, br_point *p, br_uint_32 colour)
{
br_point ap;
br_uint_16 *ptr;
//return(BRE_DEV_UNSUPPORTED);
if(PixelmapPointClip(&ap, p, (br_pixelmap *)self) == BR_CLIP_REJECT)
return BRE_OK;
MystiqueBuffersStartFrame();
msiSetParameters(NULL);
ptr = ((br_uint_16 *) msiInfo->msiColor.pMem) +
(ap.x+self->pm_base_x) +
((ap.y+self->pm_base_y) * (msiInfo->msiColor.Pitch/2));
*ptr = (br_uint_16) colour;
msiSetParameters(MSI_LFB_DISABLE);
return BRE_OK;
}
/* VERY important for text speed */
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, copyBits)
(br_device_pixelmap *self, br_point *point, br_uint_8 *src, br_uint_16 s_stride, br_rectangle *bit_rect, br_uint_32 colour)
{
br_error result;
if ((self->buffer_type != BT_BACKSCREEN) && (self->buffer_type != BT_DEPTH))
return(BRE_DEV_UNSUPPORTED);
//return(BRE_DEV_UNSUPPORTED);
MystiqueBuffersStartFrame();
msiSetParameters(NULL);
if (self->buffer_type == BT_BACKSCREEN) {
self->pm_pixels = msiInfo->msiColor.pMem;
self->pm_row_bytes = msiInfo->msiColor.Pitch;
} else {
self->pm_pixels = msiInfo->msiDepth.pMem;
self->pm_row_bytes = msiInfo->msiDepth.Pitch;
}
result = BR_CMETHOD(br_device_pixelmap_mem, copyBits)(self, point, src, s_stride, bit_rect, colour);
msiSetParameters(MSI_LFB_DISABLE);
self->pm_pixels = NULL;
self->pm_row_bytes = 0;
return result;
}
extern void StretchCopy16(
br_uint_16 *out_pixels,
br_uint_32 out_width, br_uint_32 out_height, br_uint_32 out_row_bytes,
br_uint_16 *in_pixels,
br_uint_32 in_width, br_uint_32 in_height, br_uint_32 in_row_bytes,
br_uint_32 key);
br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, rectangleStretchCopy)\
(br_device_pixelmap *self, br_rectangle *d, br_device_pixelmap *src, br_rectangle *s)
{
br_rectangle srect, drect;
br_uint_32 key, i;
if ((s->w == d->w) &&
(s->h == d->h) &&
(self->buffer_type != BT_SYSMEM)) {
br_point p;
p.x = d->x;
p.y = d->y;
return(BR_CMETHOD(br_device_pixelmap_mystique, rectangleCopyTo)(self, &p, src, s));
}
if(PixelmapRectangleClip(&drect, d, (br_pixelmap *)self) == BR_CLIP_REJECT)
return BRE_OK;
if(PixelmapRectangleClip(&srect, s, (br_pixelmap *)src) == BR_CLIP_REJECT)
return BRE_OK;
if (src->pm_type != self->pm_type)
return(BRE_DEV_UNSUPPORTED);
if ((src->pm_type != BR_PMT_RGB_555) &&
(src->pm_type != BR_PMT_RGB_565))
return(BRE_DEV_UNSUPPORTED);
MystiqueBuffersStartFrame();
if (src->pm_copy_function == BR_PMCOPY_SRC_KEYED) key = src->pm_src_key.low;
else key = 0xffff0000;
if (self->buffer_type == BT_SYSMEM) {
if (src->buffer_type != BT_SYSMEM)
return(BRE_DEV_UNSUPPORTED); /* Don't support stretches from card */
/* System-system stretch */
StretchCopy16(((br_uint_16 *)self->pm_pixels) + drect.x + (drect.y*self->pm_row_bytes/2),
drect.w, drect.h, self->pm_row_bytes,
((br_uint_16 *)src->pm_pixels) + srect.x + (srect.y*src->pm_row_bytes/2),
srect.w, srect.h, src->pm_row_bytes, key);
} else {
/* System-card stretch */
br_uint_16 *ptr;
if (self->buffer_type != BT_BACKSCREEN)
return(BRE_DEV_UNSUPPORTED);
msiSetParameters(NULL);
ptr = (br_uint_16 *) msiInfo->msiColor.pMem;
StretchCopy16(ptr + drect.x + (drect.y*self->pm_width),
drect.w, drect.h, msiInfo->msiColor.Pitch,
((br_uint_16 *)src->pm_pixels) + srect.x + (srect.y*src->pm_row_bytes/2),
srect.w, srect.h, src->pm_row_bytes, key);
msiSetParameters(MSI_LFB_DISABLE);
}
return(BRE_OK);
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, rectangleStretchCopyTo)\
(br_device_pixelmap *self, br_rectangle *d, br_device_pixelmap *src, br_rectangle *s)
{
return(BRE_DEV_UNSUPPORTED);
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, rectangleStretchCopyFrom)\
(br_device_pixelmap *self, br_rectangle *d, br_device_pixelmap *src, br_rectangle *s)
{
return(BRE_DEV_UNSUPPORTED);
}
/*
* Lock and unlock are supported here - why not...
*/
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, directLock)(br_device_pixelmap *self, br_boolean block)
{
#ifndef _WIN32
return(BRE_DEV_UNSUPPORTED);
#else
if ((self->buffer_type != BT_BACKSCREEN) && (self->buffer_type != BT_DEPTH))
return(BRE_DEV_UNSUPPORTED);
MystiqueBuffersStartFrame();
msiSetParameters(NULL);
if (self->buffer_type == BT_BACKSCREEN) {
self->pm_pixels = msiInfo->msiColor.pMem;
self->pm_row_bytes = msiInfo->msiColor.Pitch;
} else {
self->pm_pixels = msiInfo->msiDepth.pMem;
self->pm_row_bytes = msiInfo->msiDepth.Pitch;
}
return(BRE_OK);
#endif
}
static br_error BR_CMETHOD_DECL(br_device_pixelmap_mystique, directUnlock)(br_device_pixelmap *self)
{
#ifndef _WIN32
return(BRE_DEV_UNSUPPORTED);
#else
if ((self->buffer_type != BT_BACKSCREEN) && (self->buffer_type != BT_DEPTH))
return(BRE_DEV_UNSUPPORTED);
msiSetParameters(MSI_LFB_DISABLE);
self->pm_pixels = NULL;
self->pm_row_bytes = 0;
return(BRE_OK);
#endif
}
/*
* Default dispatch table for device pixelmap
*/
static struct br_device_pixelmap_dispatch devicePixelmapDispatch = {
NULL,
NULL,
NULL,
NULL,
BR_CMETHOD_REF(br_device_pixelmap_mystique, free),
BR_CMETHOD_REF(br_object_mystique, identifier),
BR_CMETHOD_REF(br_device_pixelmap_mystique, type),
BR_CMETHOD_REF(br_device_pixelmap_mystique, isType),
BR_CMETHOD_REF(br_object_mystique, device),
BR_CMETHOD_REF(br_device_pixelmap_mystique, space),
BR_CMETHOD_REF(br_device_pixelmap_mystique, queryTemplate),
BR_CMETHOD_REF(br_object, query),
BR_CMETHOD_REF(br_object, queryBuffer),
BR_CMETHOD_REF(br_object, queryMany),
BR_CMETHOD_REF(br_object, queryManySize),
BR_CMETHOD_REF(br_object, queryAll),
BR_CMETHOD_REF(br_object, queryAllSize),
BR_CMETHOD_REF(br_device_pixelmap_mem, validSource),
BR_CMETHOD_REF(br_device_pixelmap_null, resize),
BR_CMETHOD_REF(br_device_pixelmap_mystique, match),
BR_CMETHOD_REF(br_device_pixelmap_mystique, allocateSub),
BR_CMETHOD_REF(br_device_pixelmap_mystique, copy),
BR_CMETHOD_REF(br_device_pixelmap_mystique, copyTo),
BR_CMETHOD_REF(br_device_pixelmap_mystique, copyFrom),
BR_CMETHOD_REF(br_device_pixelmap_mystique, fill),
BR_CMETHOD_REF(br_device_pixelmap_mystique, doubleBuffer),
BR_CMETHOD_REF(br_device_pixelmap_gen, copyDirty),
BR_CMETHOD_REF(br_device_pixelmap_gen, copyToDirty),
BR_CMETHOD_REF(br_device_pixelmap_gen, copyFromDirty),
BR_CMETHOD_REF(br_device_pixelmap_gen, fillDirty),
BR_CMETHOD_REF(br_device_pixelmap_gen, doubleBufferDirty),
BR_CMETHOD_REF(br_device_pixelmap_gen, rectangle),
BR_CMETHOD_REF(br_device_pixelmap_gen, rectangle2),
BR_CMETHOD_REF(br_device_pixelmap_mystique, rectangleCopyTo),
BR_CMETHOD_REF(br_device_pixelmap_mystique, rectangleCopyTo),
BR_CMETHOD_REF(br_device_pixelmap_mystique, rectangleCopyFrom),
BR_CMETHOD_REF(br_device_pixelmap_mystique, rectangleStretchCopy),
BR_CMETHOD_REF(br_device_pixelmap_mystique, rectangleStretchCopyTo),
BR_CMETHOD_REF(br_device_pixelmap_mystique, rectangleStretchCopyFrom),
BR_CMETHOD_REF(br_device_pixelmap_mystique, rectangleFill),
BR_CMETHOD_REF(br_device_pixelmap_mystique, pixelSet),
BR_CMETHOD_REF(br_device_pixelmap_gen, line),
BR_CMETHOD_REF(br_device_pixelmap_mystique, copyBits),
BR_CMETHOD_REF(br_device_pixelmap_gen, text),
BR_CMETHOD_REF(br_device_pixelmap_gen, textBounds),
BR_CMETHOD_REF(br_device_pixelmap_mem, rowSize),
BR_CMETHOD_REF(br_device_pixelmap_mem, rowQuery),
BR_CMETHOD_REF(br_device_pixelmap_mem, rowSet),
BR_CMETHOD_REF(br_device_pixelmap_null, pixelQuery),
BR_CMETHOD_REF(br_device_pixelmap_null, pixelAddressQuery),
BR_CMETHOD_REF(br_device_pixelmap_null, pixelAddressSet),
BR_CMETHOD_REF(br_device_pixelmap_mem, originSet),
BR_CMETHOD_REF(br_device_pixelmap_mystique, flush),
BR_CMETHOD_REF(br_device_pixelmap_mystique, synchronise),
BR_CMETHOD_REF(br_device_pixelmap_mystique, directLock),
BR_CMETHOD_REF(br_device_pixelmap_mystique, directUnlock),
};