1427 lines
35 KiB
C
1427 lines
35 KiB
C
/*
|
|
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
|
|
*
|
|
* Device pixelmap methods
|
|
*/
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include "drv.h"
|
|
#include "pm.h"
|
|
#include "host.h"
|
|
#include "shortcut.h"
|
|
#include "brassert.h"
|
|
|
|
|
|
|
|
br_error Allocate3DfxSysMemPixelmap(br_device_pixelmap *self, br_device_pixelmap **newpm, int w, int h);
|
|
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, 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
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
* 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
|
|
};
|
|
|
|
|
|
|
|
#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
|
|
};
|
|
|
|
HWND hwnd;
|
|
|
|
#else
|
|
|
|
br_uint_32 hwnd;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
br_boolean passthru_vga;
|
|
br_uint_32 current_width;
|
|
br_uint_32 current_height;
|
|
|
|
GrLfbWriteMode_t lfb_write_mode;
|
|
GrHwConfiguration hwConfig;
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Glide error callback to replace its internal one
|
|
*/
|
|
void GlideErrorCallback( const char *string, FxBool fatal)
|
|
{
|
|
if(fatal) {
|
|
grGlideShutdown();
|
|
DriverDevice3Dfx.initialised = BR_FALSE;
|
|
BR_FATAL1("(Glide) %s", string);
|
|
} else {
|
|
#if DEBUG
|
|
BR_WARNING1("(Glide) %s", string);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Create a new device pixelmap and set a display mode
|
|
*/
|
|
br_error DevicePixelmap3DfxAllocateMode(br_device *dev, br_output_facility *facility,
|
|
br_device_pixelmap **newpm, br_token_value *tv)
|
|
{
|
|
br_device_pixelmap *self;
|
|
int i, mem, fxmem;
|
|
br_uint_16 qual;
|
|
|
|
|
|
if(dev->active_buffers[BT_FRONTSCREEN])
|
|
return(BRE_DEV_ALREADY_INIT);
|
|
|
|
if (facility->colour_type == BR_PMT_RGB_565)
|
|
lfb_write_mode = GR_LFBWRITEMODE_565;
|
|
else if (facility->colour_type == BR_PMT_RGB_555)
|
|
lfb_write_mode = GR_LFBWRITEMODE_555;
|
|
else
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
|
|
|
|
CLEAR_TEMPLATE(devicePixelmap);
|
|
CLEAR_TEMPLATE(match);
|
|
|
|
/*
|
|
* See if there is a board out there...
|
|
*/
|
|
if (!dev->initialised) {
|
|
|
|
grGlideInit();
|
|
if(!grSstQueryHardware(&hwConfig)) {
|
|
grGlideShutdown();
|
|
return BRE_DEV_HARDWARE_NOT_PRESENT;
|
|
}
|
|
dev->initialised = BR_TRUE;
|
|
}
|
|
|
|
/* Check we can support this resolution */
|
|
if (facility->width > 640) mem = 4;
|
|
else mem = 2;
|
|
for(i=0; i<hwConfig.num_sst; i++) {
|
|
if (hwConfig.SSTs[i].type == GR_SSTTYPE_VOODOO) {
|
|
fxmem = hwConfig.SSTs[i].sstBoard.VoodooConfig.fbRam;
|
|
if (fxmem < mem) {
|
|
// grGlideShutdown();
|
|
return(BRE_DEV_NO_VIDEO_MEMORY);
|
|
}
|
|
}
|
|
}
|
|
|
|
grErrorSetCallback(GlideErrorCallback);
|
|
|
|
/* We have appropriate hardware */
|
|
grSstSelect(0);
|
|
|
|
#ifdef _WIN32
|
|
{
|
|
int ScreenWidth,ScreenHeight;
|
|
struct hwnd_tokens ht;
|
|
br_int_32 count;
|
|
|
|
/* Parse for hwnd */
|
|
CLEAR_TEMPLATE(hwnd);
|
|
ht.hwnd = NULL;
|
|
hwndTemplate.res = Device3DfxResource(dev);
|
|
BrTokenValueSetMany(&ht, &count, NULL, tv, &hwndTemplate);
|
|
hwnd = ht.hwnd;
|
|
if (!hwnd)
|
|
return(BRE_DEV_FAIL);
|
|
|
|
ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
|
|
ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
SetForegroundWindow(hwnd);
|
|
MoveWindow(hwnd, 0, 0, ScreenWidth, ScreenHeight, TRUE);
|
|
}
|
|
#else
|
|
hwnd = 0;
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
* Setup mode
|
|
*/
|
|
if(!grSstWinOpen(hwnd,
|
|
facility->glide_res_code,
|
|
GR_REFRESH_60Hz,
|
|
GR_COLORFORMAT_ARGB,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
2,
|
|
1)) {
|
|
// grGlideShutdown();
|
|
return(BRE_DEV_HARDWARE_SET);
|
|
}
|
|
|
|
/*
|
|
* Clear out the buffer after that yucky splash screen
|
|
*/
|
|
grDepthMask(FXFALSE);
|
|
grRenderBuffer(GR_BUFFER_FRONTBUFFER);
|
|
grBufferClear(0,0,0xFFFF);
|
|
grRenderBuffer(GR_BUFFER_BACKBUFFER);
|
|
|
|
/* Set up default state */
|
|
grDepthBufferMode( GR_DEPTHBUFFER_ZBUFFER );
|
|
grDepthBufferFunction(GR_CMP_LEQUAL);
|
|
grDepthMask(FXTRUE);
|
|
grChromakeyValue(0);
|
|
grCullMode(GR_CULL_DISABLE);
|
|
grTexDetailControl(GR_TMU0, 0, 8, 1.0f); /* LOD bias, detail select, detail max */
|
|
grTexClampMode(GR_TMU0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
|
|
guTexCombineFunction(GR_TMU0, GR_TEXTURECOMBINE_DECAL);
|
|
|
|
|
|
/* Glide's default gamma is NOT 1.0 as suggested in the documentation; it is in
|
|
* fact 1.5 or thereabouts. This makes it a bit bright in comparison to all
|
|
* the other drivers. This brightness is not a major disadvantage; but to make
|
|
* the drivers more consistent I have (by experiment) decided 1.2 is a good
|
|
* compromise between a bright image */
|
|
grGammaCorrectionValue(1.2f);
|
|
|
|
self = BrResAllocate(Device3DfxResource(dev), sizeof(*self), BR_MEMORY_OBJECT);
|
|
|
|
self->dispatch = &devicePixelmapDispatch;
|
|
self->pm_identifier = facility->identifier;
|
|
self->restore_mode = BR_TRUE;
|
|
|
|
self->pm_pixels = 0;
|
|
|
|
self->pm_type = (br_uint_8) facility->colour_type;
|
|
self->pm_width = (br_uint_16) facility->width;
|
|
self->pm_height = (br_uint_16) facility->height;
|
|
self->pm_row_bytes = 0;
|
|
self->pm_origin_x = 0;
|
|
self->pm_origin_y = 0;
|
|
|
|
self->pm_flags = BR_PMF_NO_ACCESS;
|
|
HostSelectorDS(&qual);
|
|
self->pm_pixels_qualifier = qual;
|
|
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);
|
|
|
|
*newpm = self;
|
|
|
|
current_width = facility->width;
|
|
current_height = facility->height;
|
|
passthru_vga = BR_FALSE;
|
|
|
|
Clear3DfxStateCache();
|
|
return(BRE_OK);
|
|
}
|
|
|
|
static void BR_CMETHOD_DECL(br_device_pixelmap_3dfx, free)(br_device_pixelmap *self)
|
|
{
|
|
ObjectDevice(self)->active_buffers[self->buffer_type] = NULL;
|
|
|
|
/* Frontscreen free shuts device down */
|
|
if (self->buffer_type == BT_FRONTSCREEN) {
|
|
ObjectContainerRemove(self->output_facility, (br_object *)self);
|
|
self->output_facility->num_instances--;
|
|
|
|
/*
|
|
* Close down device
|
|
*/
|
|
grSstWinClose();
|
|
|
|
/*
|
|
* Shutdown glide library
|
|
*/
|
|
// grGlideShutdown();
|
|
}
|
|
|
|
/*
|
|
* Free up pixelmap structure
|
|
*/
|
|
BrResFreeNoCallback(self);
|
|
|
|
}
|
|
|
|
br_token BR_CMETHOD_DECL(br_device_pixelmap_3dfx, type)(br_device_pixelmap *self)
|
|
{
|
|
return BRT_DEVICE_PIXELMAP;
|
|
}
|
|
|
|
br_boolean BR_CMETHOD_DECL(br_device_pixelmap_3dfx, 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_3dfx, space)(br_device_pixelmap *self)
|
|
{
|
|
return sizeof(br_device_pixelmap);
|
|
}
|
|
|
|
struct br_tv_template * BR_CMETHOD_DECL(br_device_pixelmap_3dfx,queryTemplate)
|
|
(br_device_pixelmap *self)
|
|
{
|
|
devicePixelmapTemplate.res = Device3DfxResource(Object3DfxDevice(self));
|
|
return &devicePixelmapTemplate;
|
|
}
|
|
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_fix, flush)(
|
|
struct br_device_pixelmap *self)
|
|
{
|
|
return BRE_OK;
|
|
}
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_fix, 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_3dfx, resize)\
|
|
(br_device_pixelmap *self, br_int_32 width, br_int_32 height)
|
|
{
|
|
|
|
if (self->buffer_type != BT_FRONTSCREEN)
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
|
|
#if 0 // Disabled, no longer supported by Glide
|
|
if ((width == 0) && (height == 0)) {
|
|
/* This is a Dave 3Dfx special: resize to 0, 0 disables the passthrough connector */
|
|
grSstPassthruMode(GR_PASSTHRU_SHOW_VGA);
|
|
passthru_vga = BR_TRUE;
|
|
return(BRE_OK);
|
|
}
|
|
|
|
if (passthru_vga && (width == current_width) && (height == current_height)) {
|
|
grSstPassthruMode(GR_PASSTHRU_SHOW_SST1);
|
|
return(BRE_OK);
|
|
}
|
|
#endif
|
|
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, 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;
|
|
|
|
matchTemplate.res = Device3DfxResource(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) {
|
|
/*
|
|
* 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(Allocate3DfxSysMemPixelmap(self, newpm, mt.width, mt.height));
|
|
}
|
|
|
|
/*
|
|
* Create an offscreen buffer pixelmap
|
|
*/
|
|
pm = BrResAllocate(Device3DfxResource(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) {
|
|
|
|
/*
|
|
* 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(Device3DfxResource(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 = 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(Allocate3DfxSysMemPixelmap(self, newpm, mt.width, mt.height));
|
|
|
|
} else {
|
|
return BRE_DEV_UNSUPPORTED;
|
|
}
|
|
|
|
*newpm = pm;
|
|
|
|
return BRE_OK;
|
|
}
|
|
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, rectangleFill)
|
|
(br_device_pixelmap *self, br_rectangle *rect, br_uint_32 colour)
|
|
{
|
|
br_rectangle arect;
|
|
br_int_32 y;
|
|
br_uint_16 *ptr;
|
|
br_uint_32 *pd, c, col32;
|
|
GrLfbInfo_t info;
|
|
GrBuffer_t buffer;
|
|
GrLfbWriteMode_t mode = lfb_write_mode;
|
|
|
|
if (self->buffer_type == BT_FRONTSCREEN)
|
|
buffer = GR_BUFFER_FRONTBUFFER;
|
|
else if (self->buffer_type == BT_BACKSCREEN)
|
|
buffer = GR_BUFFER_BACKBUFFER;
|
|
else if (self->buffer_type == BT_DEPTH) {
|
|
buffer = GR_BUFFER_AUXBUFFER;
|
|
mode = GR_LFBWRITEMODE_ZA16;
|
|
} else
|
|
return(BRE_DEV_FAIL);
|
|
|
|
if(PixelmapRectangleClip(&arect, rect, (br_pixelmap *)self) == BR_CLIP_REJECT)
|
|
return BRE_OK;
|
|
|
|
info.size = sizeof(info);
|
|
if (!grLfbLock(GR_LFB_WRITE_ONLY,
|
|
buffer,
|
|
mode,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
FXFALSE,
|
|
&info)) {
|
|
|
|
/*
|
|
* Try 565 write mode if native write mode failed
|
|
*/
|
|
if (mode == GR_LFBWRITEMODE_555 && grLfbLock(GR_LFB_WRITE_ONLY,
|
|
buffer,
|
|
GR_LFBWRITEMODE_565,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
FXFALSE,
|
|
&info))
|
|
colour = colour & (1 << 5) - 1 | (colour & -(1 << 5)) << 1;
|
|
else
|
|
return(BRE_DEV_FAIL);
|
|
}
|
|
|
|
ptr = info.lfbPtr;
|
|
ptr += (arect.x+self->pm_base_x) + ((arect.y+self->pm_base_y) * info.strideInBytes/2);
|
|
|
|
col32 = colour + (((br_uint_32) colour) << 16);
|
|
|
|
for(y=0;y<arect.h;y++)
|
|
{
|
|
pd = (br_uint_32 *) ptr;
|
|
c = arect.w >> 1;
|
|
while (c--)
|
|
*pd++ = col32;
|
|
if (arect.w & 1)
|
|
*((br_uint_16 *)pd) = (br_uint_16) colour;
|
|
|
|
ptr += info.strideInBytes/2;
|
|
}
|
|
|
|
grLfbUnlock(GR_LFB_WRITE_ONLY, buffer);
|
|
|
|
return BRE_OK;
|
|
}
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, fill)(br_device_pixelmap *self, br_uint_32 colour)
|
|
{
|
|
int col;
|
|
|
|
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_3dfx, rectangleFill)(self, &rect, colour));
|
|
}
|
|
|
|
if (self->pm_type == BR_PMT_RGB_555) {
|
|
col = ((colour & 0x7c00) << 9) |
|
|
((colour & 0x03e0) << 6) |
|
|
((colour & 0x001f) << 3);
|
|
|
|
} else if (self->pm_type == BR_PMT_RGB_565) {
|
|
col = ((colour & 0xf800) << 8) |
|
|
((colour & 0x07e0) << 5) |
|
|
((colour & 0x001f) << 3);
|
|
|
|
} else
|
|
col = 0;
|
|
|
|
if(self == ObjectDevice(self)->active_buffers[BT_FRONTSCREEN]) {
|
|
grDepthMask(FXFALSE);
|
|
grRenderBuffer(GR_BUFFER_FRONTBUFFER);
|
|
grBufferClear(col,0,0xFFFF);
|
|
grRenderBuffer(GR_BUFFER_BACKBUFFER);
|
|
grDepthMask(zwrite);
|
|
}
|
|
|
|
if(self == ObjectDevice(self)->active_buffers[BT_BACKSCREEN]) {
|
|
grDepthMask(FXFALSE);
|
|
grBufferClear(col,0,0xFFFF);
|
|
grDepthMask(zwrite);
|
|
}
|
|
|
|
if(self == ObjectDevice(self)->active_buffers[BT_DEPTH]) {
|
|
grColorMask(FXFALSE,FXFALSE);
|
|
grDepthMask(FXTRUE);
|
|
grBufferClear(0,0, (br_uint_16) (colour>>16));
|
|
grColorMask(FXTRUE,FXFALSE);
|
|
grDepthMask(zwrite);
|
|
}
|
|
|
|
return BRE_OK;
|
|
}
|
|
|
|
|
|
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, copy)(br_device_pixelmap *self, br_device_pixelmap *src)
|
|
{
|
|
if (src->buffer_type == BT_SYSMEM)
|
|
return BR_CMETHOD(br_device_pixelmap_3dfx, copyTo)(self, src);
|
|
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, copyTo)(struct br_device_pixelmap *self, br_device_pixelmap *src)
|
|
{
|
|
br_uint_16 *ptr;
|
|
GrBuffer_t buffer;
|
|
GrLfbSrcFmt_t src_format;
|
|
|
|
if ((self->pm_width != src->pm_width) || (self->pm_height != src->pm_height))
|
|
return(BRE_DEV_FAIL);
|
|
|
|
if (self->buffer_type == BT_FRONTSCREEN)
|
|
buffer = GR_BUFFER_FRONTBUFFER;
|
|
else if (self->buffer_type == BT_BACKSCREEN)
|
|
buffer = GR_BUFFER_BACKBUFFER;
|
|
else if (self->buffer_type == BT_DEPTH)
|
|
buffer = GR_BUFFER_DEPTHBUFFER;
|
|
else
|
|
return(BRE_DEV_FAIL);
|
|
|
|
switch(src->pm_type) {
|
|
case BR_PMT_RGB_555:
|
|
src_format = GR_LFB_SRC_FMT_555;
|
|
break;
|
|
case BR_PMT_RGB_565:
|
|
src_format = GR_LFB_SRC_FMT_565;
|
|
break;
|
|
default:
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
ptr = src->pm_pixels;
|
|
|
|
if (!grLfbWriteRegion(buffer,
|
|
self->pm_base_x, self->pm_base_y,
|
|
src_format,
|
|
self->pm_width, self->pm_height,
|
|
src->pm_row_bytes, ptr))
|
|
return(BRE_DEV_FAIL);
|
|
|
|
return(BRE_OK);
|
|
}
|
|
|
|
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, copyFrom)(struct br_device_pixelmap *self, br_device_pixelmap *src)
|
|
{
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, 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;
|
|
|
|
/*
|
|
* Block if there is already a swap outstanding
|
|
*/
|
|
while(grBufferNumPending() != 0)
|
|
;
|
|
|
|
/*
|
|
* Do the flip...
|
|
*/
|
|
grBufferSwap(1);
|
|
|
|
grDepthMask(zwrite);
|
|
|
|
return BRE_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, pixelSet)
|
|
(br_device_pixelmap *self, br_point *p, br_uint_32 colour)
|
|
{
|
|
br_point ap;
|
|
br_uint_16 *ptr;
|
|
GrLfbInfo_t info;
|
|
GrBuffer_t buffer;
|
|
GrLfbWriteMode_t mode = lfb_write_mode;
|
|
|
|
if (self->buffer_type == BT_FRONTSCREEN)
|
|
buffer = GR_BUFFER_FRONTBUFFER;
|
|
else if (self->buffer_type == BT_BACKSCREEN)
|
|
buffer = GR_BUFFER_BACKBUFFER;
|
|
else if (self->buffer_type == BT_DEPTH) {
|
|
buffer = GR_BUFFER_AUXBUFFER;
|
|
mode = GR_LFBWRITEMODE_ZA16;
|
|
} else
|
|
return(BRE_DEV_FAIL);
|
|
|
|
if(PixelmapPointClip(&ap, p, (br_pixelmap *)self) == BR_CLIP_REJECT)
|
|
return BRE_OK;
|
|
|
|
info.size = sizeof(info);
|
|
if (!grLfbLock(GR_LFB_WRITE_ONLY,
|
|
buffer,
|
|
mode,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
FXFALSE,
|
|
&info))
|
|
return(BRE_DEV_FAIL);
|
|
|
|
ptr = info.lfbPtr;
|
|
ptr[(ap.x+self->pm_base_x) + ((ap.y+self->pm_base_y) * (info.strideInBytes/2)) ] = (FxU16)colour;
|
|
|
|
grLfbUnlock(GR_LFB_WRITE_ONLY, buffer);
|
|
|
|
|
|
return BRE_OK;
|
|
}
|
|
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, pixelQuery)
|
|
(br_device_pixelmap *self, br_uint_32 *pcolour, br_point *p)
|
|
{
|
|
br_point ap;
|
|
br_uint_16 *ptr;
|
|
GrLfbInfo_t info;
|
|
GrBuffer_t buffer;
|
|
GrLfbWriteMode_t mode = lfb_write_mode;
|
|
|
|
if (self->buffer_type == BT_FRONTSCREEN)
|
|
buffer = GR_BUFFER_FRONTBUFFER;
|
|
else if (self->buffer_type == BT_BACKSCREEN)
|
|
buffer = GR_BUFFER_BACKBUFFER;
|
|
else if (self->buffer_type == BT_DEPTH) {
|
|
buffer = GR_BUFFER_AUXBUFFER;
|
|
mode = GR_LFBWRITEMODE_ZA16;
|
|
} else
|
|
return(BRE_DEV_FAIL);
|
|
|
|
if(PixelmapPointClip(&ap, p, (br_pixelmap *)self) == BR_CLIP_REJECT)
|
|
return BRE_OK;
|
|
|
|
info.size = sizeof(info);
|
|
if (!grLfbLock( GR_LFB_READ_ONLY,
|
|
buffer,
|
|
mode,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
FXFALSE,
|
|
&info))
|
|
return(BRE_DEV_FAIL);
|
|
|
|
ptr = info.lfbPtr;
|
|
|
|
*pcolour = ptr[(ap.x+self->pm_base_x) + ((ap.y+self->pm_base_y) * (info.strideInBytes/2)) ];
|
|
|
|
grLfbUnlock(GR_LFB_READ_ONLY, buffer);
|
|
|
|
return BRE_OK;
|
|
}
|
|
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, 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;
|
|
br_uint_16 *ptr;
|
|
GrBuffer_t buffer;
|
|
GrLfbInfo_t info;
|
|
GrLfbWriteMode_t mode = lfb_write_mode;
|
|
|
|
if (self->buffer_type == BT_FRONTSCREEN)
|
|
buffer = GR_BUFFER_FRONTBUFFER;
|
|
else if (self->buffer_type == BT_BACKSCREEN)
|
|
buffer = GR_BUFFER_BACKBUFFER;
|
|
else if (self->buffer_type == BT_DEPTH) {
|
|
buffer = GR_BUFFER_AUXBUFFER;
|
|
mode = GR_LFBWRITEMODE_ZA16;
|
|
} else
|
|
return(BRE_DEV_FAIL);
|
|
|
|
info.size = sizeof(info);
|
|
if (!grLfbLock(GR_LFB_WRITE_ONLY,
|
|
buffer,
|
|
mode,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
FXFALSE,
|
|
&info))
|
|
return(BRE_DEV_FAIL);
|
|
|
|
ptr = (br_uint_16 *)info.lfbPtr;
|
|
|
|
self->pm_pixels = ptr + self->pm_base_x + (self->pm_base_y*(info.strideInBytes/2));
|
|
self->pm_row_bytes = (short) info.strideInBytes;
|
|
|
|
result = BR_CMETHOD(br_device_pixelmap_mem, copyBits)(self, point, src, s_stride, bit_rect, colour);
|
|
|
|
grLfbUnlock(GR_LFB_WRITE_ONLY, buffer);
|
|
|
|
self->pm_pixels = NULL;
|
|
self->pm_row_bytes = 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, rectangleCopy)
|
|
(br_device_pixelmap *self, br_point *p, br_device_pixelmap *src, br_rectangle *r)
|
|
{
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, rectangleCopyTo)
|
|
(br_device_pixelmap *self, br_point *p, br_device_pixelmap *src, br_rectangle *r)
|
|
{
|
|
br_rectangle ar;
|
|
br_point ap;
|
|
br_uint_16 *ptr;
|
|
GrBuffer_t buffer;
|
|
GrLfbSrcFmt_t src_format;
|
|
|
|
if (self->buffer_type == BT_FRONTSCREEN)
|
|
buffer = GR_BUFFER_FRONTBUFFER;
|
|
else if (self->buffer_type == BT_BACKSCREEN)
|
|
buffer = GR_BUFFER_BACKBUFFER;
|
|
else if (self->buffer_type == BT_DEPTH)
|
|
buffer = GR_BUFFER_DEPTHBUFFER;
|
|
else
|
|
return(BRE_DEV_FAIL);
|
|
|
|
switch(src->pm_type) {
|
|
case BR_PMT_RGB_555:
|
|
src_format = GR_LFB_SRC_FMT_555;
|
|
break;
|
|
case BR_PMT_RGB_565:
|
|
src_format = GR_LFB_SRC_FMT_565;
|
|
break;
|
|
default:
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
if(PixelmapRectangleClipTwo(&ar, &ap, r, p, (br_pixelmap *)self, (br_pixelmap *)src) == BR_CLIP_REJECT)
|
|
return BRE_OK;
|
|
|
|
ptr = src->pm_pixels;
|
|
ptr += ar.x + (ar.y * src->pm_row_bytes / 2);
|
|
|
|
if (!grLfbWriteRegion(buffer,
|
|
ap.x+self->pm_base_x, ap.y+self->pm_base_y,
|
|
src_format,
|
|
ar.w, ar.h,
|
|
src->pm_row_bytes, ptr))
|
|
return(BRE_DEV_FAIL);
|
|
|
|
return(BRE_OK);
|
|
}
|
|
|
|
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, rectangleCopyFrom)
|
|
(br_device_pixelmap *self, br_point *p, br_device_pixelmap *mem, br_rectangle *r)
|
|
{
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Local buffers for scaling
|
|
*
|
|
* Using one buffer results in long waits while the hardware finishes
|
|
* rendering to the first buffer before it can download the new texture.
|
|
* (frame rate on FX Fighter jumped from 14 fps to 20 by only allowing one buffer
|
|
* send per pass through the loop)
|
|
*/
|
|
#define SCALE_BUFFERS 2
|
|
static struct render_buffer scale_rb[SCALE_BUFFERS];
|
|
static br_uint_16 *scalebuffer[SCALE_BUFFERS] = { 0, 0 };
|
|
static GrVertex scalevtx[3];
|
|
static br_uint_32 current_scalebuffer = 0;
|
|
|
|
void init_scale_buffer(br_uint_32 i)
|
|
{
|
|
if (lfb_write_mode == GR_LFBWRITEMODE_565)
|
|
scale_rb[i].info.format = GR_TEXFMT_RGB_565;
|
|
else
|
|
scale_rb[i].info.format = GR_TEXFMT_ARGB_1555;
|
|
scale_rb[i].info.aspectRatio = GR_ASPECT_1x1;
|
|
scale_rb[i].u_range = BR_SCALAR(255.0);
|
|
scale_rb[i].v_range = BR_SCALAR(255.0);
|
|
scale_rb[i].info.largeLod = GR_LOD_256;
|
|
scale_rb[i].width_p = 256;
|
|
scale_rb[i].width_b = 512;
|
|
scale_rb[i].height = 256;
|
|
scale_rb[i].info.smallLod = GR_LOD_256;
|
|
scale_rb[i].info.data = scalebuffer[i];
|
|
scale_rb[i].tmu_id = GR_TMU0;
|
|
scale_rb[i].on_card = BR_FALSE;
|
|
scale_rb[i].uncacheable = BR_FALSE;
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
|
void fill_scalebuffer(br_uint_16 *sptr, br_uint_16 *dptr,
|
|
br_uint_32 sw, br_uint_32 sh, br_uint_32 srb, br_uint_32 drb)
|
|
{
|
|
br_uint_32 i, j;
|
|
br_uint_32 *sp, *dp;
|
|
|
|
if (sw & 1) {
|
|
/* Odd width; need to add front or back trim byte;
|
|
* attempt to align dest for maximum speed */
|
|
if (((br_uint_32) dptr) & 1) {
|
|
/* Front trim */
|
|
for(j=0;j<sh;j++) {
|
|
sp = (br_uint_32 *) sptr;
|
|
dp = (br_uint_32 *) dptr;
|
|
*(br_uint_16 *)dp++ = *(br_uint_16 *)sp++;
|
|
i = sw/2;
|
|
while(i--)
|
|
*dp++ = *sp++;
|
|
sptr += srb;
|
|
dptr += drb;
|
|
}
|
|
} else {
|
|
/* Back trim */
|
|
for(j=0;j<sh;j++) {
|
|
sp = (br_uint_32 *) sptr;
|
|
dp = (br_uint_32 *) dptr;
|
|
i = sw/2;
|
|
while(i--)
|
|
*dp++ = *sp++;
|
|
*(br_uint_16 *)dp++ = *(br_uint_16 *)sp++;
|
|
sptr += srb;
|
|
dptr += drb;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
/* Even case: no trim bytes */
|
|
for(j=0;j<sh;j++) {
|
|
sp = (br_uint_32 *) sptr;
|
|
dp = (br_uint_32 *) dptr;
|
|
i = sw/2;
|
|
while(i--)
|
|
*dp++ = *sp++;
|
|
sptr += srb;
|
|
dptr += drb;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void copy_scalebuffer(GrTextureFilterMode_t filter)
|
|
{
|
|
extern br_error FXCacheTexture(struct render_buffer *src);
|
|
|
|
scale_rb[current_scalebuffer].force_reload = 1;
|
|
FXCacheTexture(&scale_rb[current_scalebuffer]);
|
|
grTexSource(scale_rb[current_scalebuffer].tmu_id,
|
|
scale_rb[current_scalebuffer].startAddress,
|
|
GR_MIPMAPLEVELMASK_BOTH,
|
|
&scale_rb[current_scalebuffer].info );
|
|
grTexFilterMode(scale_rb[current_scalebuffer].tmu_id, filter, filter);
|
|
grTexClampMode( scale_rb[current_scalebuffer].tmu_id,
|
|
GR_TEXTURECLAMP_CLAMP,
|
|
GR_TEXTURECLAMP_CLAMP );
|
|
}
|
|
|
|
|
|
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, 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_3dfx, 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);
|
|
|
|
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 */
|
|
#if 0
|
|
br_uint_16 *ptr;
|
|
|
|
/* Setup Glide for LFB writes */
|
|
grLfbBegin();
|
|
grLfbBypassMode(GR_LFBBYPASS_ENABLE);
|
|
|
|
ptr = grLfbGetWritePtr( GR_BUFFER_BACKBUFFER );
|
|
grLfbWriteMode( lfb_write_mode );
|
|
|
|
StretchCopy16(ptr + drect.x + (drect.y*1024),
|
|
drect.w, drect.h, 2048,
|
|
((br_uint_16 *)src->pm_pixels) + srect.x + (srect.y*src->pm_row_bytes/2),
|
|
srect.w, srect.h, src->pm_row_bytes, key);
|
|
|
|
/* Deinit LFB */
|
|
grLfbEnd();
|
|
#else
|
|
/* Hardware stretch */
|
|
if (!scalebuffer[0]) {
|
|
/* First time; set up everything */
|
|
for(i=0; i<SCALE_BUFFERS; i++) {
|
|
scalebuffer[i] = BrResAllocate(Device3DfxResource(ObjectDevice(self)),
|
|
256*256*2, BR_MEMORY_DRIVER);
|
|
init_scale_buffer(i);
|
|
}
|
|
scalevtx[0].ooz = 65530.0f;
|
|
scalevtx[1].ooz = 65530.0f;
|
|
scalevtx[2].ooz = 65530.0f;
|
|
scalevtx[0].oow = 1.0f;
|
|
scalevtx[1].oow = 1.0f;
|
|
scalevtx[2].oow = 1.0f;
|
|
scalevtx[0].tmuvtx[0].oow = 1.0f;
|
|
scalevtx[1].tmuvtx[0].oow = 1.0f;
|
|
scalevtx[2].tmuvtx[0].oow = 1.0f;
|
|
}
|
|
|
|
/* WARNING: possible state corruption */
|
|
grTexCombineFunction(0,GR_TEXTURECOMBINE_DECAL);
|
|
guColorCombineFunction(GR_COLORCOMBINE_DECAL_TEXTURE);
|
|
/*
|
|
* Removed by <REDACTEDPROGRAMMER> as its a pile of shite and lies,
|
|
* at least in the specific use in <REDACTEDGAME>!
|
|
* grHints(GR_HINT_STWHINT, GR_STWHINT_W_DIFF_TMU0 );
|
|
*/
|
|
grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO,
|
|
GR_BLEND_ONE, GR_BLEND_ZERO);
|
|
|
|
{
|
|
br_uint_32 sx, sy, sw, sh, xscale;
|
|
br_uint_32 dx, dy, dw, dh, aspect;
|
|
br_uint_16 *sptr, *dptr;
|
|
GrTextureFilterMode_t filter;
|
|
float fdx, fdy, fdw, fdh;
|
|
|
|
|
|
sx = 0; /* Offsets from start */
|
|
sy = 0;
|
|
dx = 0;
|
|
dy = 0;
|
|
xscale = (drect.w << 16) / srect.w;
|
|
|
|
sh = srect.h;
|
|
if (sh > 256) sh = 256;
|
|
dh = drect.h;
|
|
|
|
grDepthBufferMode(GR_DEPTHBUFFER_DISABLE);
|
|
if (src->pm_copy_function == BR_PMCOPY_SRC_KEYED) {
|
|
grChromakeyMode(GR_CHROMAKEY_ENABLE);
|
|
#if 0
|
|
key = ((src->pm_src_key.low & 0xf800) << 8) |
|
|
((src->pm_src_key.low & 0x07e0) << 5) |
|
|
((src->pm_src_key.low & 0x001f) << 3) ;
|
|
grChromakeyValue(key);
|
|
#endif
|
|
} else
|
|
grChromakeyMode(GR_CHROMAKEY_DISABLE);
|
|
|
|
/* Disabled because it causes seaming and chromakey problems */
|
|
// filter = GR_TEXTUREFILTER_BILINEAR,
|
|
filter = GR_TEXTUREFILTER_POINT_SAMPLED;
|
|
|
|
while (1) {
|
|
sw = srect.w - sx;
|
|
|
|
/* Stop if run out of data */
|
|
if (sw <= 0)
|
|
break;
|
|
|
|
/* Max width in one go is 256x256 */
|
|
if (sw > 256) {
|
|
/* OK try to be devious; make the FIRST block sent the small - and
|
|
* therefore fast - one. */
|
|
if (((srect.w - sx) - 256) <= 128) {
|
|
sw = (srect.w - sx) - 256;
|
|
} else
|
|
sw = 256;
|
|
}
|
|
|
|
/* Fix up aspect ratio to reduce data sent to card */
|
|
if (sw <= 32) {
|
|
aspect = 8;
|
|
scale_rb[current_scalebuffer].info.aspectRatio = GR_ASPECT_1x8;
|
|
} else if (sw <= 32) {
|
|
aspect = 4;
|
|
scale_rb[current_scalebuffer].info.aspectRatio = GR_ASPECT_1x4;
|
|
} else if (sw <= 128) {
|
|
aspect = 2;
|
|
scale_rb[current_scalebuffer].info.aspectRatio = GR_ASPECT_1x2;
|
|
} else {
|
|
aspect = 1;
|
|
scale_rb[current_scalebuffer].info.aspectRatio = GR_ASPECT_1x1;
|
|
}
|
|
|
|
dw = (sw * xscale) >> 16;
|
|
|
|
/* Copy from source pixelmap to texture */
|
|
sptr = ((br_uint_16 *)src->pm_pixels) +
|
|
(srect.x+sx) +
|
|
((srect.y+sy)*src->pm_row_bytes/2),
|
|
dptr = scalebuffer[current_scalebuffer];
|
|
fill_scalebuffer(sptr, dptr, sw, sh, src->pm_row_bytes/2, 256/aspect);
|
|
|
|
/* Copy Texture across to card*/
|
|
copy_scalebuffer(filter);
|
|
|
|
/* Build vertices */
|
|
fdx = (float) (drect.x + dx);
|
|
fdy = (float) (drect.y + dy);
|
|
fdw = (float) dw;
|
|
fdh = (float) dh;
|
|
scalevtx[0].x = fdx;
|
|
scalevtx[0].y = fdy;
|
|
scalevtx[0].tmuvtx[0].sow = 0.0f;
|
|
scalevtx[0].tmuvtx[0].tow = 0.0f;
|
|
scalevtx[1].x = fdx + fdw;
|
|
scalevtx[1].y = fdy;
|
|
scalevtx[1].tmuvtx[0].sow = (float) sw;
|
|
scalevtx[1].tmuvtx[0].tow = 0.0f;
|
|
scalevtx[2].x = fdx + fdw;
|
|
scalevtx[2].y = fdy + fdh;
|
|
scalevtx[2].tmuvtx[0].sow = (float) sw;
|
|
scalevtx[2].tmuvtx[0].tow = (float) sh;
|
|
|
|
grDrawTriangle(scalevtx+0, scalevtx+1, scalevtx+2);
|
|
|
|
scalevtx[0].x = fdx;
|
|
scalevtx[0].y = fdy;
|
|
scalevtx[0].tmuvtx[0].sow = 0.0f;
|
|
scalevtx[0].tmuvtx[0].tow = 0.0f;
|
|
scalevtx[1].x = fdx + fdw;
|
|
scalevtx[1].y = fdy + fdh;
|
|
scalevtx[1].tmuvtx[0].sow = (float) sw;
|
|
scalevtx[1].tmuvtx[0].tow = (float) sh;
|
|
scalevtx[2].x = fdx;
|
|
scalevtx[2].y = fdy + fdh;
|
|
scalevtx[2].tmuvtx[0].sow = 0.0f;
|
|
scalevtx[2].tmuvtx[0].tow = (float) sh;
|
|
|
|
grDrawTriangle(scalevtx+0, scalevtx+1, scalevtx+2);
|
|
|
|
sx += sw;
|
|
dx += dw;
|
|
current_scalebuffer = (current_scalebuffer+1) % SCALE_BUFFERS;
|
|
//break;
|
|
}
|
|
grChromakeyValue(0);
|
|
grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
|
|
}
|
|
|
|
|
|
#endif
|
|
}
|
|
|
|
return(BRE_OK);
|
|
}
|
|
|
|
|
|
br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, 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(Device3DfxResource(Object3DfxDevice(self)),sizeof(*pm),BR_MEMORY_PIXELMAP);
|
|
|
|
// 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_3dfx, rectangleStretchCopyTo)\
|
|
(br_device_pixelmap *self, br_rectangle *d, br_device_pixelmap *src, br_rectangle *s)
|
|
{
|
|
BR_CMETHOD(br_device_pixelmap_3dfx, rectangleFill)(self, d, 0);
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, rectangleStretchCopyFrom)\
|
|
(br_device_pixelmap *self, br_rectangle *d, br_device_pixelmap *src, br_rectangle *s)
|
|
{
|
|
return(BRE_DEV_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
|
|
static GrBuffer_t last_lock_buffer;
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, directLock)(br_device_pixelmap *self, br_boolean block)
|
|
{
|
|
br_uint_16 *ptr;
|
|
GrBuffer_t buffer;
|
|
GrLfbInfo_t info;
|
|
GrLfbWriteMode_t mode = lfb_write_mode;
|
|
|
|
if (self->buffer_type == BT_FRONTSCREEN)
|
|
buffer = GR_BUFFER_FRONTBUFFER;
|
|
else if (self->buffer_type == BT_BACKSCREEN)
|
|
buffer = GR_BUFFER_BACKBUFFER;
|
|
else if (self->buffer_type == BT_DEPTH) {
|
|
buffer = GR_BUFFER_AUXBUFFER;
|
|
mode = GR_LFBWRITEMODE_ZA16;
|
|
} else
|
|
return(BRE_DEV_FAIL);
|
|
|
|
info.size = sizeof(info);
|
|
if (!grLfbLock(GR_LFB_WRITE_ONLY,
|
|
buffer,
|
|
mode,
|
|
GR_ORIGIN_UPPER_LEFT,
|
|
FXFALSE,
|
|
&info))
|
|
return(BRE_DEV_FAIL);
|
|
|
|
/* Added by Matt : */
|
|
ptr = (br_uint_16 *)info.lfbPtr;
|
|
|
|
self->pm_pixels = ptr + self->pm_base_x + (self->pm_base_y*(info.strideInBytes/2));
|
|
self->pm_row_bytes = (short) info.strideInBytes;
|
|
last_lock_buffer = buffer;
|
|
|
|
return(BRE_OK);
|
|
}
|
|
|
|
static br_error BR_CMETHOD_DECL(br_device_pixelmap_3dfx, directUnlock)(br_device_pixelmap *self)
|
|
{
|
|
grLfbUnlock(GR_LFB_WRITE_ONLY, last_lock_buffer);
|
|
|
|
self->pm_pixels = NULL;
|
|
self->pm_row_bytes = 0;
|
|
|
|
return(BRE_OK);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Default dispatch table for device pixelmap
|
|
*/
|
|
static struct br_device_pixelmap_dispatch devicePixelmapDispatch = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, free),
|
|
BR_CMETHOD_REF(br_object_3dfx, identifier),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, type),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, isType),
|
|
BR_CMETHOD_REF(br_object_3dfx, device),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, space),
|
|
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, 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_3dfx, resize),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, match),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, allocateSub),
|
|
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, copy),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, copyTo),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, copyFrom),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, fill),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, 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_3dfx, rectangleCopy),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, rectangleCopyTo),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, rectangleCopyFrom),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, rectangleStretchCopy),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, rectangleStretchCopyTo),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, rectangleStretchCopyFrom),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, rectangleFill),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, pixelSet),
|
|
BR_CMETHOD_REF(br_device_pixelmap_gen, line),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, 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_3dfx, 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_fix, flush),
|
|
BR_CMETHOD_REF(br_device_pixelmap_fix, synchronise),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, directLock),
|
|
BR_CMETHOD_REF(br_device_pixelmap_3dfx, directUnlock),
|
|
};
|
|
|