1
0
Fork 0

(svn r10121) -Codechange: split renderer from rest of code; no longer any code directly accesses the video-buffer

-Add: added NULL blitter and renderer, which are always used for -vnull
-Add: dedicated driver doesn't blit nor render by default. Can be overruled by user. (-D -b 8bpp-optimized)
-Remove: removed CTRL+D from win32, which is incompatible with above
-Add: extended screenshot support for PNG and BMP
-Codechange: remove all hardcoded 8bpp references and replace them with more dynamic ones
-Codechange: minor stuff in blitters
release/0.6
truelight 2007-06-12 20:24:12 +00:00
parent 381b11c979
commit f3f744d36a
31 changed files with 687 additions and 294 deletions

View File

@ -979,6 +979,12 @@
<File <File
RelativePath=".\..\src\blitter\8bpp_simple.hpp"> RelativePath=".\..\src\blitter\8bpp_simple.hpp">
</File> </File>
<File
RelativePath=".\..\src\blitter\null.cpp">
</File>
<File
RelativePath=".\..\src\blitter\null.hpp">
</File>
<File <File
RelativePath=".\..\src\blitter\blitter.hpp"> RelativePath=".\..\src\blitter\blitter.hpp">
</File> </File>
@ -996,6 +1002,25 @@
RelativePath=".\..\src\spriteloader\spriteloader.hpp"> RelativePath=".\..\src\spriteloader\spriteloader.hpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="Renderer"
Filter="">
<File
RelativePath=".\..\src\renderer\8bpp.cpp">
</File>
<File
RelativePath=".\..\src\renderer\8bpp.hpp">
</File>
<File
RelativePath=".\..\src\renderer\null.cpp">
</File>
<File
RelativePath=".\..\src\renderer\null.hpp">
</File>
<File
RelativePath=".\..\src\renderer\renderer.hpp">
</File>
</Filter>
<Filter <Filter
Name="NewGRF" Name="NewGRF"
Filter=""> Filter="">

View File

@ -1527,6 +1527,14 @@
RelativePath=".\..\src\blitter\8bpp_simple.hpp" RelativePath=".\..\src\blitter\8bpp_simple.hpp"
> >
</File> </File>
<File
RelativePath=".\..\src\blitter\null.cpp"
>
</File>
<File
RelativePath=".\..\src\blitter\null.hpp"
>
</File>
<File <File
RelativePath=".\..\src\blitter\blitter.hpp" RelativePath=".\..\src\blitter\blitter.hpp"
> >
@ -1548,6 +1556,30 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="Renderer"
>
<File
RelativePath=".\..\src\renderer\8bpp.cpp"
>
</File>
<File
RelativePath=".\..\src\renderer\8bpp.hpp"
>
</File>
<File
RelativePath=".\..\src\renderer\null.cpp"
>
</File>
<File
RelativePath=".\..\src\renderer\null.hpp"
>
</File>
<File
RelativePath=".\..\src\renderer\renderer.hpp"
>
</File>
</Filter>
<Filter <Filter
Name="NewGRF" Name="NewGRF"
> >

View File

@ -297,6 +297,8 @@ blitter/8bpp_optimized.cpp
blitter/8bpp_optimized.hpp blitter/8bpp_optimized.hpp
blitter/8bpp_simple.cpp blitter/8bpp_simple.cpp
blitter/8bpp_simple.hpp blitter/8bpp_simple.hpp
blitter/null.cpp
blitter/null.hpp
blitter/blitter.hpp blitter/blitter.hpp
# Sprite loaders # Sprite loaders
@ -304,6 +306,13 @@ spriteloader/grf.cpp
spriteloader/grf.hpp spriteloader/grf.hpp
spriteloader/spriteloader.hpp spriteloader/spriteloader.hpp
# Renderer
renderer/8bpp.cpp
renderer/8bpp.hpp
renderer/null.cpp
renderer/null.hpp
renderer/renderer.hpp
# NewGRF # NewGRF
newgrf.cpp newgrf.cpp
newgrf_canal.cpp newgrf_canal.cpp

View File

@ -12,12 +12,12 @@ static FBlitter_8bppDebug iFBlitter_8bppDebug;
void Blitter_8bppDebug::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) void Blitter_8bppDebug::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{ {
const byte *src, *src_line; const uint8 *src, *src_line;
Pixel8 *dst, *dst_line; uint8 *dst, *dst_line;
/* Find where to start reading in the source sprite */ /* Find where to start reading in the source sprite */
src_line = (const byte *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom); src_line = (const uint8 *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left; dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
for (int y = 0; y < bp->height; y++) { for (int y = 0; y < bp->height; y++) {
dst = dst_line; dst = dst_line;

View File

@ -7,15 +7,15 @@
#include "blitter.hpp" #include "blitter.hpp"
typedef Pixel Pixel8;
class Blitter_8bppDebug : public Blitter { class Blitter_8bppDebug : public Blitter {
public: public:
uint8 GetScreenDepth() { return 8; } /* virtual */ uint8 GetScreenDepth() { return 8; }
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom); /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator); /* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
/* virtual */ const char *GetRenderer() { return "8bpp"; }
}; };
class FBlitter_8bppDebug: public BlitterFactory<FBlitter_8bppDebug> { class FBlitter_8bppDebug: public BlitterFactory<FBlitter_8bppDebug> {

View File

@ -12,16 +12,16 @@ static FBlitter_8bppOptimized iFBlitter_8bppOptimized;
void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{ {
const byte *src, *src_next; const uint8 *src, *src_next;
Pixel8 *dst, *dst_line; uint8 *dst, *dst_line;
uint offset = 0; uint offset = 0;
/* Find the offset of this zoom-level */ /* Find the offset of this zoom-level */
offset = ((const byte *)bp->sprite)[(int)zoom * 2] | ((const byte *)bp->sprite)[(int)zoom * 2 + 1] << 8; offset = ((const uint8 *)bp->sprite)[(int)zoom * 2] | ((const byte *)bp->sprite)[(int)zoom * 2 + 1] << 8;
/* Find where to start reading in the source sprite */ /* Find where to start reading in the source sprite */
src = (const byte *)bp->sprite + offset; src = (const uint8 *)bp->sprite + offset;
dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left; dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
/* Skip over the top lines in the source image */ /* Skip over the top lines in the source image */
for (int y = 0; y < bp->skip_top; y++) { for (int y = 0; y < bp->skip_top; y++) {

View File

@ -7,15 +7,15 @@
#include "blitter.hpp" #include "blitter.hpp"
typedef Pixel Pixel8;
class Blitter_8bppOptimized : public Blitter { class Blitter_8bppOptimized : public Blitter {
public: public:
uint8 GetScreenDepth() { return 8; } /* virtual */ uint8 GetScreenDepth() { return 8; }
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom); /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator); /* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
/* virtual */ const char *GetRenderer() { return "8bpp"; }
}; };
class FBlitter_8bppOptimized: public BlitterFactory<FBlitter_8bppOptimized> { class FBlitter_8bppOptimized: public BlitterFactory<FBlitter_8bppOptimized> {

View File

@ -11,12 +11,12 @@ static FBlitter_8bppSimple iFBlitter_8bppSimple;
void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{ {
const byte *src, *src_line; const uint8 *src, *src_line;
Pixel8 *dst, *dst_line; uint8 *dst, *dst_line;
/* Find where to start reading in the source sprite */ /* Find where to start reading in the source sprite */
src_line = (const byte *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom); src_line = (const uint8 *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left; dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
for (int y = 0; y < bp->height; y++) { for (int y = 0; y < bp->height; y++) {
dst = dst_line; dst = dst_line;

View File

@ -7,15 +7,15 @@
#include "blitter.hpp" #include "blitter.hpp"
typedef Pixel Pixel8;
class Blitter_8bppSimple : public Blitter { class Blitter_8bppSimple : public Blitter {
public: public:
uint8 GetScreenDepth() { return 8; } /* virtual */ uint8 GetScreenDepth() { return 8; }
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom); /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator); /* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
/* virtual */ const char *GetRenderer() { return "8bpp"; }
}; };
class FBlitter_8bppSimple: public BlitterFactory<FBlitter_8bppSimple> { class FBlitter_8bppSimple: public BlitterFactory<FBlitter_8bppSimple> {

View File

@ -53,6 +53,11 @@ public:
*/ */
virtual Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator) = 0; virtual Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator) = 0;
/**
* Get the renderer this class depends on.
*/
virtual const char *GetRenderer() = 0;
virtual ~Blitter() { } virtual ~Blitter() { }
}; };

View File

@ -0,0 +1,24 @@
#include "../stdafx.h"
#include "../zoom.hpp"
#include "../gfx.h"
#include "../functions.h"
#include "null.hpp"
static FBlitter_Null iFBlitter_Null;
void Blitter_Null::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{
}
Sprite *Blitter_Null::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
{
Sprite *dest_sprite;
dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite));
dest_sprite->height = sprite->height;
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
return dest_sprite;
}

View File

@ -0,0 +1,30 @@
/* $Id$ */
/** @file null.hpp */
#ifndef BLITTER_NULL_HPP
#define BLITTER_NULL_HPP
#include "blitter.hpp"
class Blitter_Null : public Blitter {
public:
/* virtual */ uint8 GetScreenDepth() { return 0; }
/* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
/* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
/* virtual */ const char *GetRenderer() { return "null"; }
};
class FBlitter_Null: public BlitterFactory<FBlitter_Null> {
public:
/* virtual */ const char *GetName() { return "null"; }
/* virtual */ const char *GetDescription() { return "Null Blitter (does nothing)"; }
/* virtual */ Blitter *CreateInstance() { return new Blitter_Null(); }
};
#endif /* BLITTER_NULL_HPP */

View File

@ -50,7 +50,7 @@ static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
FontSize _cur_fontsize; FontSize _cur_fontsize;
static FontSize _last_fontsize; static FontSize _last_fontsize;
static Pixel _cursor_backup[64 * 64]; static uint8 _cursor_backup[64 * 64 * 4];
static Rect _invalid_rect; static Rect _invalid_rect;
static const byte *_color_remap_ptr; static const byte *_color_remap_ptr;
static byte _string_colorremap[3]; static byte _string_colorremap[3];
@ -58,37 +58,20 @@ static byte _string_colorremap[3];
#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64) #define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64)
static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8]; static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8];
void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch)
{
Pixel *dstp = (Pixel *)dst;
Pixel *srcp = (Pixel *)src;
assert(h >= 0);
for (; h != 0; --h) {
memcpy(dstp, srcp, w * sizeof(Pixel));
dstp += dstpitch;
srcp += srcpitch;
}
}
void GfxScroll(int left, int top, int width, int height, int xo, int yo) void GfxScroll(int left, int top, int width, int height, int xo, int yo)
{ {
const Pixel *src; const void *src;
Pixel *dst; void *dst;
int p;
int ht;
if (xo == 0 && yo == 0) return; if (xo == 0 && yo == 0) return;
if (_cursor.visible) UndrawMouseCursor(); if (_cursor.visible) UndrawMouseCursor();
UndrawTextMessage(); UndrawTextMessage();
p = _screen.pitch;
if (yo > 0) { if (yo > 0) {
/*Calculate pointers */ /*Calculate pointers */
dst = _screen.dst_ptr + (top + height - 1) * p + left; dst = _screen.renderer->MoveTo(_screen.dst_ptr, left, top + height - 1);
src = dst - yo * p; src = _screen.renderer->MoveTo(dst, 0, -yo);
/* Decrease height and increase top */ /* Decrease height and increase top */
top += yo; top += yo;
@ -97,23 +80,20 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
/* Adjust left & width */ /* Adjust left & width */
if (xo >= 0) { if (xo >= 0) {
dst += xo; dst = _screen.renderer->MoveTo(dst, xo, 0);
left += xo; left += xo;
width -= xo; width -= xo;
} else { } else {
src -= xo; src = _screen.renderer->MoveTo(src, -xo, 0);
width += xo; width += xo;
} }
for (ht = height; ht > 0; --ht) { /* Negative height as we want to copy from bottom to top */
memcpy(dst, src, width * sizeof(Pixel)); _screen.renderer->CopyFromBuffer(dst, src, width, -height, _screen.pitch);
src -= p;
dst -= p;
}
} else { } else {
/* Calculate pointers */ /* Calculate pointers */
dst = _screen.dst_ptr + top * p + left; dst = _screen.renderer->MoveTo(_screen.dst_ptr, left, top);
src = dst - yo * p; src = _screen.renderer->MoveTo(dst, 0, -yo);
/* Decrese height. (yo is <=0). */ /* Decrese height. (yo is <=0). */
height += yo; height += yo;
@ -121,21 +101,17 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
/* Adjust left & width */ /* Adjust left & width */
if (xo >= 0) { if (xo >= 0) {
dst += xo; dst = _screen.renderer->MoveTo(dst, xo, 0);
left += xo; left += xo;
width -= xo; width -= xo;
} else { } else {
src -= xo; src = _screen.renderer->MoveTo(src, -xo, 0);
width += xo; width += xo;
} }
/* the y-displacement may be 0 therefore we have to use memmove, /* the y-displacement may be 0 therefore we have to use memmove,
* because source and destination may overlap */ * because source and destination may overlap */
for (ht = height; ht > 0; --ht) { _screen.renderer->MoveBuffer(dst, src, width, height);
memmove(dst, src, width * sizeof(Pixel));
src += p;
dst += p;
}
} }
/* This part of the screen is now dirty. */ /* This part of the screen is now dirty. */
_video_driver->make_dirty(left, top, width, height); _video_driver->make_dirty(left, top, width, height);
@ -144,8 +120,8 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
void GfxFillRect(int left, int top, int right, int bottom, int color) void GfxFillRect(int left, int top, int right, int bottom, int color)
{ {
const DrawPixelInfo* dpi = _cur_dpi; const DrawPixelInfo *dpi = _cur_dpi;
Pixel *dst; void *dst;
const int otop = top; const int otop = top;
const int oleft = left; const int oleft = left;
@ -166,40 +142,37 @@ void GfxFillRect(int left, int top, int right, int bottom, int color)
bottom -= top; bottom -= top;
assert(bottom > 0); assert(bottom > 0);
dst = dpi->dst_ptr + top * dpi->pitch + left; dst = _screen.renderer->MoveTo(dpi->dst_ptr, left, top);
if (!HASBIT(color, PALETTE_MODIFIER_GREYOUT)) { if (!HASBIT(color, PALETTE_MODIFIER_GREYOUT)) {
if (!HASBIT(color, USE_COLORTABLE)) { if (!HASBIT(color, USE_COLORTABLE)) {
do { do {
memset(dst, color, right * sizeof(Pixel)); _screen.renderer->SetHorizontalLine(dst, right, (uint8)color);
dst += dpi->pitch; dst = _screen.renderer->MoveTo(dst, 0, 1);
} while (--bottom); } while (--bottom);
} else { } else {
/* use colortable mode */ /* use colortable mode */
const byte* ctab = GetNonSprite(GB(color, 0, PALETTE_WIDTH)) + 1; const byte* ctab = GetNonSprite(GB(color, 0, PALETTE_WIDTH)) + 1;
do { do {
int i; for (int i = 0; i != right; i++) _screen.renderer->SetPixel(dst, i, 0, ctab[((uint8 *)dst)[i]]);
for (i = 0; i != right; i++) dst[i] = ctab[dst[i]]; dst = _screen.renderer->MoveTo(dst, 0, 1);
dst += dpi->pitch;
} while (--bottom); } while (--bottom);
} }
} else { } else {
byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1; byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
do { do {
int i; for (int i = (bo ^= 1); i < right; i += 2) _screen.renderer->SetPixel(dst, i, 0, (uint8)color);
for (i = (bo ^= 1); i < right; i += 2) dst[i] = (byte)color; dst = _screen.renderer->MoveTo(dst, 0, 1);
dst += dpi->pitch;
} while (--bottom > 0); } while (--bottom > 0);
} }
} }
static void GfxSetPixel(int x, int y, int color) static void GfxSetPixel(int x, int y, int color)
{ {
const DrawPixelInfo* dpi = _cur_dpi; const DrawPixelInfo *dpi = _cur_dpi;
if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top)<0 || y >= dpi->height) if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top) < 0 || y >= dpi->height) return;
return; _screen.renderer->SetPixel(dpi->dst_ptr, x, y, color);
dpi->dst_ptr[y * dpi->pitch + x] = color;
} }
void GfxDrawLine(int x, int y, int x2, int y2, int color) void GfxDrawLine(int x, int y, int x2, int y2, int color)
@ -817,6 +790,13 @@ void DoPaletteAnimations()
Colour old_val[38]; // max(38, 28) Colour old_val[38]; // max(38, 28)
uint i; uint i;
uint j; uint j;
int old_tc = _timer_counter;
/* We can only update the palette in 8bpp for now */
/* TODO -- We need support for other bpps too! */
if (BlitterFactoryBase::GetCurrentBlitter() != NULL && BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) {
_timer_counter = 0;
}
d = &_cur_palette[217]; d = &_cur_palette[217];
memcpy(old_val, d, c * sizeof(*old_val)); memcpy(old_val, d, c * sizeof(*old_val));
@ -913,6 +893,8 @@ void DoPaletteAnimations()
if (_pal_first_dirty > 217) _pal_first_dirty = 217; if (_pal_first_dirty > 217) _pal_first_dirty = 217;
if (_pal_last_dirty < 217 + c) _pal_last_dirty = 217 + c; if (_pal_last_dirty < 217 + c) _pal_last_dirty = 217 + c;
} }
if (old_tc != _timer_counter) _timer_counter = old_tc;
} }
@ -959,11 +941,7 @@ void UndrawMouseCursor()
{ {
if (_cursor.visible) { if (_cursor.visible) {
_cursor.visible = false; _cursor.visible = false;
memcpy_pitch( _screen.renderer->CopyFromBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), _cursor_backup, _cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x);
_screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch,
_cursor_backup,
_cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x, _screen.pitch);
_video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); _video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y);
} }
} }
@ -1006,13 +984,10 @@ void DrawMouseCursor()
_cursor.draw_pos.y = y; _cursor.draw_pos.y = y;
_cursor.draw_size.y = h; _cursor.draw_size.y = h;
assert(w * h < (int)sizeof(_cursor_backup)); assert(_screen.renderer->BufferSize(w, h) < (int)sizeof(_cursor_backup));
/* Make backup of stuff below cursor */ /* Make backup of stuff below cursor */
memcpy_pitch( _screen.renderer->CopyToBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), _cursor_backup, _cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x);
_cursor_backup,
_screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch,
_cursor.draw_size.x, _cursor.draw_size.y, _screen.pitch, _cursor.draw_size.x);
/* Draw cursor on screen */ /* Draw cursor on screen */
_cur_dpi = &_screen; _cur_dpi = &_screen;
@ -1233,7 +1208,8 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int heigh
n->top = 0; n->top = 0;
} }
n->dst_ptr = o->dst_ptr + left + top * (n->pitch = o->pitch); n->dst_ptr = _screen.renderer->MoveTo(o->dst_ptr, left, top);
n->pitch = o->pitch;
if (height > o->height - top) { if (height > o->height - top) {
height = o->height - top; height = o->height - top;

View File

@ -7,6 +7,7 @@
#include "openttd.h" #include "openttd.h"
#include "zoom.hpp" #include "zoom.hpp"
#include "renderer/renderer.hpp"
enum WindowKeyCodes { enum WindowKeyCodes {
WKC_SHIFT = 0x8000, WKC_SHIFT = 0x8000,
@ -93,7 +94,6 @@ void GameLoop();
void CreateConsole(); void CreateConsole();
typedef int32 CursorID; typedef int32 CursorID;
typedef byte Pixel;
struct Point { struct Point {
int x,y; int x,y;
@ -134,10 +134,11 @@ struct CursorVars {
}; };
struct DrawPixelInfo { struct DrawPixelInfo {
Pixel *dst_ptr; void *dst_ptr;
int left, top, width, height; int left, top, width, height;
int pitch; int pitch;
ZoomLevel zoom; ZoomLevel zoom;
Renderer *renderer;
}; };
struct Colour { struct Colour {

View File

@ -402,6 +402,7 @@ int ttd_main(int argc, char *argv[])
strcpy(musicdriver, "null"); strcpy(musicdriver, "null");
strcpy(sounddriver, "null"); strcpy(sounddriver, "null");
strcpy(videodriver, "dedicated"); strcpy(videodriver, "dedicated");
strcpy(blitter, "null");
dedicated = true; dedicated = true;
if (mgo.opt != NULL) { if (mgo.opt != NULL) {
/* Use the existing method for parsing (openttd -n). /* Use the existing method for parsing (openttd -n).

View File

@ -0,0 +1,71 @@
#include "../stdafx.h"
#include "../gfx.h"
#include "8bpp.hpp"
static FRenderer_8bpp iFRenderer_8bpp;
void *Renderer_8bpp::MoveTo(const void *video, int x, int y)
{
return (uint8 *)video + x + y * _screen.pitch;
}
void Renderer_8bpp::SetPixel(void *video, int x, int y, uint8 color)
{
*((uint8 *)video + x + y * _screen.pitch) = color;
}
void Renderer_8bpp::SetPixelIfEmpty(void *video, int x, int y, uint8 color)
{
uint8 *dst = (uint8 *)video + x + y * _screen.pitch;
if (*dst == 0) *dst = color;
}
void Renderer_8bpp::SetHorizontalLine(void *video, int width, uint8 color)
{
memset(video, color, width);
}
void Renderer_8bpp::CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch)
{
int direction = (height < 0) ? -1 : 1;
uint8 *dst = (uint8 *)video;
uint8 *usrc = (uint8 *)src;
height = abs(height);
for (; height > 0; height--) {
memcpy(dst, usrc, width);
usrc += src_pitch * direction;
dst += _screen.pitch * direction;
}
}
void Renderer_8bpp::CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)
{
int direction = (height < 0) ? -1 : 1;
uint8 *udst = (uint8 *)dst;
uint8 *src = (uint8 *)video;
height = abs(height);
for (; height > 0; height--) {
memcpy(udst, src, width);
src += _screen.pitch * direction;
udst += dst_pitch * direction;
}
}
void Renderer_8bpp::MoveBuffer(void *video_dst, const void *video_src, int width, int height)
{
uint8 *dst = (uint8 *)video_dst;
uint8 *src = (uint8 *)video_src;
for (; height > 0; height--) {
memmove(dst, src, width);
src += _screen.pitch;
dst += _screen.pitch;
}
}
int Renderer_8bpp::BufferSize(int width, int height)
{
return width * height;
}

View File

@ -0,0 +1,29 @@
/* $Id$ */
/** @file 8bpp.hpp */
#ifndef RENDERER_8BPP_HPP
#define RENDERER_8BPP_HPP
#include "renderer.hpp"
class Renderer_8bpp : public Renderer {
public:
/* virtual */ void *MoveTo(const void *video, int x, int y);
/* virtual */ void SetPixel(void *video, int x, int y, uint8 color);
/* virtual */ void SetPixelIfEmpty(void *video, int x, int y, uint8 color);
/* virtual */ void SetHorizontalLine(void *video, int width, uint8 color);
/* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch);
/* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch);
/* virtual */ void MoveBuffer(void *video_dst, const void *video_src, int width, int height);
/* virtual */ int BufferSize(int width, int height);
};
class FRenderer_8bpp: public RendererFactory<FRenderer_8bpp> {
public:
/* virtual */ const char *GetName() { return "8bpp"; }
/* virtual */ Renderer *CreateInstance() { return new Renderer_8bpp(); }
};
#endif /* RENDERER_8BPP_HPP */

View File

@ -0,0 +1,39 @@
#include "../stdafx.h"
#include "../gfx.h"
#include "null.hpp"
static FRenderer_Null iFRenderer_Null;
void *Renderer_Null::MoveTo(const void *video, int x, int y)
{
return NULL;
}
void Renderer_Null::SetPixel(void *video, int x, int y, uint8 color)
{
}
void Renderer_Null::SetPixelIfEmpty(void *video, int x, int y, uint8 color)
{
}
void Renderer_Null::SetHorizontalLine(void *video, int width, uint8 color)
{
}
void Renderer_Null::CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch)
{
}
void Renderer_Null::CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)
{
}
void Renderer_Null::MoveBuffer(void *video_dst, const void *video_src, int width, int height)
{
}
int Renderer_Null::BufferSize(int width, int height)
{
return 0;
}

View File

@ -0,0 +1,29 @@
/* $Id$ */
/** @file null.hpp */
#ifndef RENDERER_NULL_HPP
#define RENDERER_NULL_HPP
#include "renderer.hpp"
class Renderer_Null : public Renderer {
public:
/* virtual */ void *MoveTo(const void *video, int x, int y);
/* virtual */ void SetPixel(void *video, int x, int y, uint8 color);
/* virtual */ void SetPixelIfEmpty(void *video, int x, int y, uint8 color);
/* virtual */ void SetHorizontalLine(void *video, int width, uint8 color);
/* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch);
/* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch);
/* virtual */ void MoveBuffer(void *video_dst, const void *video_src, int width, int height);
/* virtual */ int BufferSize(int width, int height);
};
class FRenderer_Null: public RendererFactory<FRenderer_Null> {
public:
/* virtual */ const char *GetName() { return "null"; }
/* virtual */ Renderer *CreateInstance() { return new Renderer_Null(); }
};
#endif /* RENDERER_NULL_HPP */

View File

@ -0,0 +1,165 @@
/* $Id$ */
/** @file renderer.hpp */
#ifndef RENDERER_HPP
#define RENDERER_HPP
#include <string>
#include <map>
class Renderer {
public:
virtual ~Renderer() { }
/**
* Move the destination pointer the requested amount x and y, keeping in mind
* any pitch and bpp of the renderer.
* @param video The destination pointer (video-buffer) to scroll.
* @param x How much you want to scroll to the right.
* @param y How much you want to scroll to the bottom.
* @return A new destination pointer moved the the requested place.
*/
virtual void *MoveTo(const void *video, int x, int y) = 0;
/**
* Draw a pixel with a given color on the video-buffer.
* @param video The destination pointer (video-buffer).
* @param x The x position within video-buffer.
* @param y The y position within video-buffer.
* @param color A 8bpp mapping color.
*/
virtual void SetPixel(void *video, int x, int y, uint8 color) = 0;
/**
* Draw a pixel with a given color on the video-buffer if there is currently a black pixel.
* @param video The destination pointer (video-buffer).
* @param x The x position within video-buffer.
* @param y The y position within video-buffer.
* @param color A 8bpp mapping color.
*/
virtual void SetPixelIfEmpty(void *video, int x, int y, uint8 color) = 0;
/**
* Make a single horizontal line in a single color on the video-buffer.
* @param video The destination pointer (video-buffer).
* @param width The lenght of the line.
* @param color A 8bpp mapping color.
*/
virtual void SetHorizontalLine(void *video, int width, uint8 color) = 0;
/**
* Copy from a buffer to the screen.
* @param video The destionation pointer (video-buffer).
* @param src The buffer from which the data will be read.
* @param width The width of the buffer.
* @param height The height of the buffer.
* @param src_pitch The pitch (byte per line) of the source buffer.
*/
virtual void CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch) = 0;
/**
* Copy from the screen to a buffer.
* @param video The destination pointer (video-buffer).
* @param dst The buffer in which the data will be stored.
* @param width The width of the buffer.
* @param height The height of the buffer.
* @param dst_pitch The pitch (byte per line) of the destination buffer.
*/
virtual void CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) = 0;
/**
* Move the videobuffer some places (via memmove).
* @param video_dst The destination pointer (video-buffer).
* @param video_src The source pointer (video-buffer).
* @param width The width of the buffer to move.
* @param height The height of the buffer to move.
*/
virtual void MoveBuffer(void *video_dst, const void *video_src, int width, int height) = 0;
/**
* Calculate how much memory there is needed for an image of this size in the video-buffer.
* @param width The width of the buffer-to-be.
* @param height The height of the buffer-to-be.
* @return The size needed for the buffer.
*/
virtual int BufferSize(int width, int height) = 0;
};
/**
* The factory, keeping track of all renderers.
*/
class RendererFactoryBase {
private:
char *name;
typedef std::map<std::string, RendererFactoryBase *> Renderers;
static Renderers &GetRenderers()
{
static Renderers &s_renderers = *new Renderers();
return s_renderers;
}
protected:
/**
* Register a renderer internally, based on his bpp.
* @param name the name of the renderer.
* @note an assert() will be trigger if 2 renderers with the same bpp try to register.
*/
void RegisterRenderer(const char *name)
{
/* Don't register nameless Renderers */
if (name == NULL) return;
this->name = strdup(name);
std::pair<Renderers::iterator, bool> P = GetRenderers().insert(Renderers::value_type(name, this));
assert(P.second);
}
public:
RendererFactoryBase() :
name(NULL)
{ }
virtual ~RendererFactoryBase() { if (this->name != NULL) GetRenderers().erase(this->name); free(this->name); }
/**
* Find the requested renderer and return his class-instance.
* @param name the renderer to select.
*/
static Renderer *SelectRenderer(const char *name)
{
if (GetRenderers().size() == 0) return NULL;
Renderers::iterator it = GetRenderers().begin();
for (; it != GetRenderers().end(); it++) {
RendererFactoryBase *r = (*it).second;
if (strcasecmp(name, r->name) == 0) {
return r->CreateInstance();
}
}
return NULL;
}
/**
* Create an instance of this Renderer-class.
*/
virtual Renderer *CreateInstance() = 0;
};
/**
* A template factory, so ->GetBpp() works correctly. This because else some compiler will complain.
*/
template <class T>
class RendererFactory: public RendererFactoryBase {
public:
RendererFactory() { this->RegisterRenderer(((T *)this)->GetName()); }
/**
* Get the name for this renderer.
*/
const char *GetName();
};
#endif /* RENDERER_HPP */

View File

@ -14,6 +14,7 @@
#include "variables.h" #include "variables.h"
#include "date.h" #include "date.h"
#include "helpers.hpp" #include "helpers.hpp"
#include "blitter/blitter.hpp"
#include "fileio.h" #include "fileio.h"
char _screenshot_format_name[8]; char _screenshot_format_name[8];
@ -22,7 +23,7 @@ uint _cur_screenshot_format;
ScreenshotType current_screenshot_type; ScreenshotType current_screenshot_type;
/* called by the ScreenShot proc to generate screenshot lines. */ /* called by the ScreenShot proc to generate screenshot lines. */
typedef void ScreenshotCallback(void *userdata, Pixel *buf, uint y, uint pitch, uint n); typedef void ScreenshotCallback(void *userdata, void *buf, uint y, uint pitch, uint n);
typedef bool ScreenshotHandlerProc(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette); typedef bool ScreenshotHandlerProc(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette);
struct ScreenshotFormat { struct ScreenshotFormat {
@ -72,10 +73,11 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
FILE *f; FILE *f;
uint i, padw; uint i, padw;
uint n, maxlines; uint n, maxlines;
uint pal_size = 0;
uint bpp = pixelformat / 8;
/* only implemented for 8bit images so far. */ /* only implemented for 8bit and 32bit images so far. */
if (pixelformat != 8) if (pixelformat != 8 && pixelformat != 32) return false;
return false;
f = fopen(name, "wb"); f = fopen(name, "wb");
if (f == NULL) return false; if (f == NULL) return false;
@ -83,18 +85,20 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
/* each scanline must be aligned on a 32bit boundary */ /* each scanline must be aligned on a 32bit boundary */
padw = ALIGN(w, 4); padw = ALIGN(w, 4);
if (pixelformat == 8) pal_size = sizeof(RgbQuad) * 256;
/* setup the file header */ /* setup the file header */
bfh.type = TO_LE16('MB'); bfh.type = TO_LE16('MB');
bfh.size = TO_LE32(sizeof(bfh) + sizeof(bih) + sizeof(RgbQuad) * 256 + padw * h); bfh.size = TO_LE32(sizeof(bfh) + sizeof(bih) + pal_size + padw * h * bpp);
bfh.reserved = 0; bfh.reserved = 0;
bfh.off_bits = TO_LE32(sizeof(bfh) + sizeof(bih) + sizeof(RgbQuad) * 256); bfh.off_bits = TO_LE32(sizeof(bfh) + sizeof(bih) + pal_size);
/* setup the info header */ /* setup the info header */
bih.size = TO_LE32(sizeof(BitmapInfoHeader)); bih.size = TO_LE32(sizeof(BitmapInfoHeader));
bih.width = TO_LE32(w); bih.width = TO_LE32(w);
bih.height = TO_LE32(h); bih.height = TO_LE32(h);
bih.planes = TO_LE16(1); bih.planes = TO_LE16(1);
bih.bitcount = TO_LE16(8); bih.bitcount = TO_LE16(pixelformat);
bih.compression = 0; bih.compression = 0;
bih.sizeimage = 0; bih.sizeimage = 0;
bih.xpels = 0; bih.xpels = 0;
@ -102,24 +106,26 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
bih.clrused = 0; bih.clrused = 0;
bih.clrimp = 0; bih.clrimp = 0;
/* convert the palette to the windows format */ if (pixelformat == 8) {
for (i = 0; i != 256; i++) { /* convert the palette to the windows format */
rq[i].red = palette[i].r; for (i = 0; i != 256; i++) {
rq[i].green = palette[i].g; rq[i].red = palette[i].r;
rq[i].blue = palette[i].b; rq[i].green = palette[i].g;
rq[i].reserved = 0; rq[i].blue = palette[i].b;
rq[i].reserved = 0;
}
} }
/* write file header and info header and palette */ /* write file header and info header and palette */
if (fwrite(&bfh, sizeof(bfh), 1, f) != 1) return false; if (fwrite(&bfh, sizeof(bfh), 1, f) != 1) return false;
if (fwrite(&bih, sizeof(bih), 1, f) != 1) return false; if (fwrite(&bih, sizeof(bih), 1, f) != 1) return false;
if (fwrite(rq, sizeof(rq), 1, f) != 1) return false; if (pixelformat == 8) if (fwrite(rq, sizeof(rq), 1, f) != 1) return false;
/* use by default 64k temp memory */ /* use by default 64k temp memory */
maxlines = clamp(65536 / padw, 16, 128); maxlines = clamp(65536 / padw, 16, 128);
/* now generate the bitmap bits */ /* now generate the bitmap bits */
Pixel *buff = MallocT<Pixel>(padw * maxlines); // by default generate 128 lines at a time. void *buff = MallocT<uint8>(padw * maxlines * bpp); // by default generate 128 lines at a time.
if (buff == NULL) { if (buff == NULL) {
fclose(f); fclose(f);
return false; return false;
@ -137,7 +143,7 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
/* write each line */ /* write each line */
while (n) while (n)
if (fwrite(buff + (--n) * padw, padw, 1, f) != 1) { if (fwrite((uint8 *)buff + (--n) * padw * bpp, padw * bpp, 1, f) != 1) {
free(buff); free(buff);
fclose(f); fclose(f);
return false; return false;
@ -173,12 +179,12 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
FILE *f; FILE *f;
uint i, y, n; uint i, y, n;
uint maxlines; uint maxlines;
uint bpp = pixelformat / 8;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
/* only implemented for 8bit images so far. */ /* only implemented for 8bit and 32bit images so far. */
if (pixelformat != 8) if (pixelformat != 8 && pixelformat != 32) return false;
return false;
f = fopen(name, "wb"); f = fopen(name, "wb");
if (f == NULL) return false; if (f == NULL) return false;
@ -207,31 +213,53 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
png_set_IHDR(png_ptr, info_ptr, w, h, pixelformat, PNG_COLOR_TYPE_PALETTE, png_set_IHDR(png_ptr, info_ptr, w, h, 8, pixelformat == 8 ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
/* convert the palette to the .PNG format. */ if (pixelformat == 8) {
for (i = 0; i != 256; i++) { /* convert the palette to the .PNG format. */
rq[i].red = palette[i].r; for (i = 0; i != 256; i++) {
rq[i].green = palette[i].g; rq[i].red = palette[i].r;
rq[i].blue = palette[i].b; rq[i].green = palette[i].g;
rq[i].blue = palette[i].b;
}
png_set_PLTE(png_ptr, info_ptr, rq, 256);
} }
png_set_PLTE(png_ptr, info_ptr, rq, 256);
png_write_info(png_ptr, info_ptr); png_write_info(png_ptr, info_ptr);
png_set_flush(png_ptr, 512); png_set_flush(png_ptr, 512);
if (pixelformat == 32) {
png_color_8 sig_bit;
/* Save exact color/alpha resolution */
sig_bit.alpha = 0;
sig_bit.blue = 8;
sig_bit.green = 8;
sig_bit.red = 8;
sig_bit.gray = 8;
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
#ifdef TTD_LITTLE_ENDIAN
png_set_bgr(png_ptr);
png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
#else
png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
#endif
}
/* use by default 64k temp memory */ /* use by default 64k temp memory */
maxlines = clamp(65536 / w, 16, 128); maxlines = clamp(65536 / w, 16, 128);
/* now generate the bitmap bits */ /* now generate the bitmap bits */
Pixel *buff = MallocT<Pixel>(w * maxlines); // by default generate 128 lines at a time. void *buff = MallocT<uint8>(w * maxlines * bpp); // by default generate 128 lines at a time.
if (buff == NULL) { if (buff == NULL) {
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(f); fclose(f);
return false; return false;
} }
memset(buff, 0, w * maxlines); // zero the buffer to have the padding bytes set to 0 memset(buff, 0, w * maxlines * bpp);
y = 0; y = 0;
do { do {
@ -244,7 +272,7 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
/* write them to png */ /* write them to png */
for (i = 0; i != n; i++) for (i = 0; i != n; i++)
png_write_row(png_ptr, buff + i * w); png_write_row(png_ptr, (png_bytep)buff + i * w * bpp);
} while (y != h); } while (y != h);
png_write_end(png_ptr, info_ptr); png_write_end(png_ptr, info_ptr);
@ -288,6 +316,10 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
PcxHeader pcx; PcxHeader pcx;
bool success; bool success;
if (pixelformat == 32) {
DEBUG(misc, 0, "Can't convert a 32bpp screenshot to PCX format. Please pick an other format.");
return false;
}
if (pixelformat != 8 || w == 0) if (pixelformat != 8 || w == 0)
return false; return false;
@ -321,7 +353,7 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
maxlines = clamp(65536 / w, 16, 128); maxlines = clamp(65536 / w, 16, 128);
/* now generate the bitmap bits */ /* now generate the bitmap bits */
Pixel *buff = MallocT<Pixel>(w * maxlines); // by default generate 128 lines at a time. uint8 *buff = MallocT<uint8>(w * maxlines); // by default generate 128 lines at a time.
if (buff == NULL) { if (buff == NULL) {
fclose(f); fclose(f);
return false; return false;
@ -340,14 +372,14 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
/* write them to pcx */ /* write them to pcx */
for (i = 0; i != n; i++) { for (i = 0; i != n; i++) {
const Pixel* bufp = buff + i * w; const uint8 *bufp = buff + i * w;
byte runchar = bufp[0]; byte runchar = bufp[0];
uint runcount = 1; uint runcount = 1;
uint j; uint j;
/* for each pixel... */ /* for each pixel... */
for (j = 1; j < w; j++) { for (j = 1; j < w; j++) {
Pixel ch = bufp[j]; uint8 ch = bufp[j];
if (ch != runchar || runcount >= 0x3f) { if (ch != runchar || runcount >= 0x3f) {
if (runcount > 1 || (runchar & 0xC0) == 0xC0) if (runcount > 1 || (runchar & 0xC0) == 0xC0)
@ -447,17 +479,14 @@ void SetScreenshotFormat(int i)
} }
/* screenshot generator that dumps the current video buffer */ /* screenshot generator that dumps the current video buffer */
static void CurrentScreenCallback(void *userdata, Pixel *buf, uint y, uint pitch, uint n) static void CurrentScreenCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
{ {
for (; n > 0; --n) { void *src = _screen.renderer->MoveTo(_screen.dst_ptr, 0, y);
memcpy(buf, _screen.dst_ptr + y * _screen.pitch, _screen.width * sizeof(Pixel)); _screen.renderer->CopyToBuffer(src, buf, _screen.width, n, pitch);
++y;
buf += pitch;
}
} }
/* generate a large piece of the world */ /* generate a large piece of the world */
static void LargeWorldCallback(void *userdata, Pixel *buf, uint y, uint pitch, uint n) static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
{ {
ViewPort *vp = (ViewPort *)userdata; ViewPort *vp = (ViewPort *)userdata;
DrawPixelInfo dpi, *old_dpi; DrawPixelInfo dpi, *old_dpi;
@ -534,7 +563,7 @@ bool IsScreenshotRequested()
static bool MakeSmallScreenshot() static bool MakeSmallScreenshot()
{ {
const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format; const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format;
return sf->proc(MakeScreenshotName(sf->extension), CurrentScreenCallback, NULL, _screen.width, _screen.height, 8, _cur_palette); return sf->proc(MakeScreenshotName(sf->extension), CurrentScreenCallback, NULL, _screen.width, _screen.height, BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(), _cur_palette);
} }
static bool MakeWorldScreenshot() static bool MakeWorldScreenshot()
@ -553,7 +582,7 @@ static bool MakeWorldScreenshot()
vp.height = vp.virtual_height; vp.height = vp.virtual_height;
sf = _screenshot_formats + _cur_screenshot_format; sf = _screenshot_formats + _cur_screenshot_format;
return sf->proc(MakeScreenshotName(sf->extension), LargeWorldCallback, &vp, vp.width, vp.height, 8, _cur_palette); return sf->proc(MakeScreenshotName(sf->extension), LargeWorldCallback, &vp, vp.width, vp.height, BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(), _cur_palette);
} }
bool MakeScreenshot() bool MakeScreenshot()

View File

@ -1225,14 +1225,13 @@ static const SettingDesc _music_settings[] = {
/* win32_v.c only settings */ /* win32_v.c only settings */
#ifdef WIN32 #ifdef WIN32
extern bool _force_full_redraw, _double_size, _window_maximize; extern bool _force_full_redraw, _window_maximize;
extern uint _display_hz, _fullscreen_bpp; extern uint _display_hz, _fullscreen_bpp;
static const SettingDescGlobVarList _win32_settings[] = { static const SettingDescGlobVarList _win32_settings[] = {
SDTG_VAR("display_hz", SLE_UINT, S, 0, _display_hz, 0, 0, 120, 0, STR_NULL, NULL), SDTG_VAR("display_hz", SLE_UINT, S, 0, _display_hz, 0, 0, 120, 0, STR_NULL, NULL),
SDTG_BOOL("force_full_redraw", S, 0, _force_full_redraw,false, STR_NULL, NULL), SDTG_BOOL("force_full_redraw", S, 0, _force_full_redraw,false, STR_NULL, NULL),
SDTG_VAR("fullscreen_bpp", SLE_UINT, S, 0, _fullscreen_bpp, 8, 8, 32, 0, STR_NULL, NULL), SDTG_VAR("fullscreen_bpp", SLE_UINT, S, 0, _fullscreen_bpp, 8, 8, 32, 0, STR_NULL, NULL),
SDTG_BOOL("double_size", S, 0, _double_size, false, STR_NULL, NULL),
SDTG_BOOL("window_maximize", S, 0, _window_maximize, false, STR_NULL, NULL), SDTG_BOOL("window_maximize", S, 0, _window_maximize, false, STR_NULL, NULL),
SDTG_END() SDTG_END()
}; };

View File

@ -167,41 +167,23 @@ static const LegendAndColour * const _legend_table[] = {
_legend_land_owners, _legend_land_owners,
}; };
#if defined(OTTD_ALIGNMENT) static inline void WRITE_PIXELS(void *d, uint32 val)
static inline void WRITE_PIXELS(Pixel* d, uint32 val) {
{ uint8 *val8 = (uint8 *)&val;
# if defined(TTD_BIG_ENDIAN) _screen.renderer->SetPixel(d, 0, 0, val8[0]);
d[0] = GB(val, 24, 8); _screen.renderer->SetPixel(d, 1, 0, val8[1]);
d[1] = GB(val, 16, 8); _screen.renderer->SetPixel(d, 2, 0, val8[2]);
d[2] = GB(val, 8, 8); _screen.renderer->SetPixel(d, 3, 0, val8[3]);
d[3] = GB(val, 0, 8); }
# elif defined(TTD_LITTLE_ENDIAN)
d[0] = GB(val, 0, 8);
d[1] = GB(val, 8, 8);
d[2] = GB(val, 16, 8);
d[3] = GB(val, 24, 8);
# endif
}
/* need to use OR, otherwise we will overwrite the wrong pixels at the edges :( */ static inline void WRITE_PIXELS_OR(void *d, uint32 val)
static inline void WRITE_PIXELS_OR(Pixel *d, uint32 val) {
{ uint8 *val8 = (uint8 *)&val;
# if defined(TTD_BIG_ENDIAN) _screen.renderer->SetPixelIfEmpty(d, 0, 0, val8[0]);
d[0] |= GB(val, 24, 8); _screen.renderer->SetPixelIfEmpty(d, 1, 0, val8[1]);
d[1] |= GB(val, 16, 8); _screen.renderer->SetPixelIfEmpty(d, 2, 0, val8[2]);
d[2] |= GB(val, 8, 8); _screen.renderer->SetPixelIfEmpty(d, 3, 0, val8[3]);
d[3] |= GB(val, 0, 8); }
# elif defined(TTD_LITTLE_ENDIAN)
d[0] |= GB(val, 0, 8);
d[1] |= GB(val, 8, 8);
d[2] |= GB(val, 16, 8);
d[3] |= GB(val, 24, 8);
# endif
}
#else
# define WRITE_PIXELS(dst, val) *(uint32*)(dst) = (val);
# define WRITE_PIXELS_OR(dst,val) *(uint32*)(dst) |= (val);
#endif
#define MKCOLOR(x) TO_LE32X(x) #define MKCOLOR(x) TO_LE32X(x)
@ -296,9 +278,9 @@ typedef uint32 GetSmallMapPixels(TileIndex tile); // typedef callthrough functio
* @param proc Pointer to the colour function * @param proc Pointer to the colour function
* @see GetSmallMapPixels(TileIndex) * @see GetSmallMapPixels(TileIndex)
*/ */
static void DrawSmallMapStuff(Pixel *dst, uint xc, uint yc, int pitch, int reps, uint32 mask, GetSmallMapPixels *proc) static void DrawSmallMapStuff(void *dst, uint xc, uint yc, int pitch, int reps, uint32 mask, GetSmallMapPixels *proc)
{ {
Pixel *dst_ptr_end = _screen.dst_ptr + _screen.width * _screen.height - _screen.width; void *dst_ptr_end = _screen.renderer->MoveTo(_screen.dst_ptr, _screen.width, _screen.height - 1);
do { do {
/* check if the tile (xc,yc) is within the map range */ /* check if the tile (xc,yc) is within the map range */
@ -308,7 +290,7 @@ static void DrawSmallMapStuff(Pixel *dst, uint xc, uint yc, int pitch, int reps,
WRITE_PIXELS_OR(dst, proc(TileXY(xc, yc)) & mask); WRITE_PIXELS_OR(dst, proc(TileXY(xc, yc)) & mask);
} }
/* switch to next tile in the column */ /* switch to next tile in the column */
} while (xc++, yc++, dst += pitch, --reps != 0); } while (xc++, yc++, dst = _screen.renderer->MoveTo(dst, pitch, 0), --reps != 0);
} }
@ -530,7 +512,7 @@ static void DrawSmallMap(DrawPixelInfo *dpi, Window *w, int type, bool show_town
{ {
DrawPixelInfo *old_dpi; DrawPixelInfo *old_dpi;
int dx,dy, x, y, x2, y2; int dx,dy, x, y, x2, y2;
Pixel *ptr; void *ptr;
int tile_x; int tile_x;
int tile_y; int tile_y;
ViewPort *vp; ViewPort *vp;
@ -582,7 +564,7 @@ static void DrawSmallMap(DrawPixelInfo *dpi, Window *w, int type, bool show_town
} }
} }
ptr = dpi->dst_ptr - dx - 4; ptr = _screen.renderer->MoveTo(dpi->dst_ptr, -dx - 4, 0);
x = - dx - 4; x = - dx - 4;
y = 0; y = 0;
@ -609,7 +591,6 @@ static void DrawSmallMap(DrawPixelInfo *dpi, Window *w, int type, bool show_town
/* number of lines */ /* number of lines */
reps = (dpi->height - y + 1) / 2; reps = (dpi->height - y + 1) / 2;
if (reps > 0) { if (reps > 0) {
// assert(ptr >= dpi->dst_ptr);
DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]); DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]);
} }
@ -617,13 +598,13 @@ skip_column:
if (y == 0) { if (y == 0) {
tile_y++; tile_y++;
y++; y++;
ptr += dpi->pitch; ptr = _screen.renderer->MoveTo(ptr, 0, 1);
} else { } else {
tile_x--; tile_x--;
y--; y--;
ptr -= dpi->pitch; ptr = _screen.renderer->MoveTo(ptr, 0, -1);
} }
ptr += 2; ptr = _screen.renderer->MoveTo(ptr, 2, 0);
x += 2; x += 2;
} }
@ -666,12 +647,11 @@ skip_column:
} }
/* Calculate pointer to pixel and the color */ /* Calculate pointer to pixel and the color */
ptr = dpi->dst_ptr + y * dpi->pitch + x;
color = (type == 1) ? _vehicle_type_colors[v->type] : 0xF; color = (type == 1) ? _vehicle_type_colors[v->type] : 0xF;
/* And draw either one or two pixels depending on clipping */ /* And draw either one or two pixels depending on clipping */
ptr[0] = color; _screen.renderer->SetPixel(dpi->dst_ptr, x, y, color);
if (!skip) ptr[1] = color; if (!skip) _screen.renderer->SetPixel(dpi->dst_ptr, x + 1, y, color);;
} }
} }
} }

View File

@ -54,9 +54,7 @@ static bool _textmessage_visible = false;
/* The chatbox grows from the bottom so the coordinates are pixels from /* The chatbox grows from the bottom so the coordinates are pixels from
* the left and pixels from the bottom. The height is the maximum height */ * the left and pixels from the bottom. The height is the maximum height */
static const Oblong _textmsg_box = {10, 30, 500, 150}; static const Oblong _textmsg_box = {10, 30, 500, 150};
static Pixel _textmessage_backup[150 * 500]; // (height * width) static uint8 _textmessage_backup[150 * 500 * 4]; // (height * width)
extern void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch);
static inline uint GetTextMessageCount() static inline uint GetTextMessageCount()
{ {
@ -163,11 +161,7 @@ void UndrawTextMessage()
_textmessage_visible = false; _textmessage_visible = false;
/* Put our 'shot' back to the screen */ /* Put our 'shot' back to the screen */
memcpy_pitch( _screen.renderer->CopyFromBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, x, y), _textmessage_backup, width, height, _textmsg_box.width);
_screen.dst_ptr + x + y * _screen.pitch,
_textmessage_backup,
width, height, _textmsg_box.width, _screen.pitch);
/* And make sure it is updated next time */ /* And make sure it is updated next time */
_video_driver->make_dirty(x, y, width, height); _video_driver->make_dirty(x, y, width, height);
@ -227,10 +221,7 @@ void DrawTextMessage()
if (width <= 0 || height <= 0) return; if (width <= 0 || height <= 0) return;
/* Make a copy of the screen as it is before painting (for undraw) */ /* Make a copy of the screen as it is before painting (for undraw) */
memcpy_pitch( _screen.renderer->CopyToBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, x, y), _textmessage_backup, width, height, _textmsg_box.width);
_textmessage_backup,
_screen.dst_ptr + x + y * _screen.pitch,
width, height, _screen.pitch, _textmsg_box.width);
_cur_dpi = &_screen; // switch to _screen painting _cur_dpi = &_screen; // switch to _screen painting

View File

@ -69,6 +69,7 @@ extern "C" void HideMenuBar();
#include "../macros.h" #include "../macros.h"
#include "../os/macosx/splash.h" #include "../os/macosx/splash.h"
#include "../variables.h" #include "../variables.h"
#include "../blitter/blitter.hpp"
#include "cocoa_v.h" #include "cocoa_v.h"
#include "cocoa_keys.h" #include "cocoa_keys.h"
@ -950,6 +951,10 @@ static void QZ_SetPortAlphaOpaque()
static void QZ_UpdateWindowPalette(uint start, uint count) static void QZ_UpdateWindowPalette(uint start, uint count)
{ {
/* We can only update the palette in 8bpp for now */
/* TODO -- We need support for other bpps too! */
if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) return;
uint i; uint i;
switch (_cocoa_video_data.device_bpp) { switch (_cocoa_video_data.device_bpp) {

View File

@ -13,6 +13,7 @@
#include "../console.h" #include "../console.h"
#include "../variables.h" #include "../variables.h"
#include "../genworld.h" #include "../genworld.h"
#include "../blitter/blitter.hpp"
#include "dedicated_v.h" #include "dedicated_v.h"
#ifdef BEOS_NET_SERVER #ifdef BEOS_NET_SERVER
@ -112,7 +113,7 @@ static void CloseWindowsConsoleThread()
#endif #endif
static Pixel *_dedicated_video_mem; static void *_dedicated_video_mem;
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm); extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
extern void SwitchMode(int new_mode); extern void SwitchMode(int new_mode);
@ -120,9 +121,14 @@ extern void SwitchMode(int new_mode);
static const char *DedicatedVideoStart(const char * const *parm) static const char *DedicatedVideoStart(const char * const *parm)
{ {
int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
if (bpp == 0) _dedicated_video_mem = NULL;
else _dedicated_video_mem = malloc(_cur_resolution[0] * _cur_resolution[1] * (bpp / 8));
_screen.width = _screen.pitch = _cur_resolution[0]; _screen.width = _screen.pitch = _cur_resolution[0];
_screen.height = _cur_resolution[1]; _screen.height = _cur_resolution[1];
_dedicated_video_mem = (Pixel *)malloc(_cur_resolution[0] * _cur_resolution[1] * sizeof(Pixel)); _screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
SetDebugString("net=6"); SetDebugString("net=6");

View File

@ -5,19 +5,23 @@
#include "../gfx.h" #include "../gfx.h"
#include "../variables.h" #include "../variables.h"
#include "../window.h" #include "../window.h"
#include "../debug.h"
#include "../blitter/blitter.hpp"
#include "null_v.h" #include "null_v.h"
static Pixel *_null_video_mem = NULL;
static const char* NullVideoStart(const char* const* parm) static const char* NullVideoStart(const char* const* parm)
{ {
_screen.width = _screen.pitch = _cur_resolution[0]; _screen.width = _screen.pitch = _cur_resolution[0];
_screen.height = _cur_resolution[1]; _screen.height = _cur_resolution[1];
_null_video_mem = (Pixel *)malloc(_cur_resolution[0] * _cur_resolution[1] * sizeof(Pixel)); /* Do not render, nor blit */
DEBUG(misc, 1, "Forcing blitter 'null'...");
BlitterFactoryBase::SelectBlitter("null");
_screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
return NULL; return NULL;
} }
static void NullVideoStop() { free(_null_video_mem); } static void NullVideoStop() { }
static void NullVideoMakeDirty(int left, int top, int width, int height) {} static void NullVideoMakeDirty(int left, int top, int width, int height) {}
@ -27,7 +31,7 @@ static void NullVideoMainLoop()
for (i = 0; i < 1000; i++) { for (i = 0; i < 1000; i++) {
GameLoop(); GameLoop();
_screen.dst_ptr = _null_video_mem; _screen.dst_ptr = NULL;
UpdateWindows(); UpdateWindows();
} }
} }

View File

@ -13,6 +13,8 @@
#include "../window.h" #include "../window.h"
#include "../network/network.h" #include "../network/network.h"
#include "../variables.h" #include "../variables.h"
#include "../blitter/blitter.hpp"
#include "../renderer/renderer.hpp"
#include "sdl_v.h" #include "sdl_v.h"
#include <SDL.h> #include <SDL.h>
@ -36,6 +38,10 @@ static void SdlVideoMakeDirty(int left, int top, int width, int height)
static void UpdatePalette(uint start, uint count) static void UpdatePalette(uint start, uint count)
{ {
/* We can only update the palette in 8bpp for now */
/* TODO -- We need support for other bpps too! */
if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) return;
SDL_Color pal[256]; SDL_Color pal[256];
uint i; uint i;
@ -172,10 +178,13 @@ static bool CreateMainSurface(int w, int h)
extern const char _openttd_revision[]; extern const char _openttd_revision[];
SDL_Surface *newscreen, *icon; SDL_Surface *newscreen, *icon;
char caption[50]; char caption[50];
int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
GetAvailableVideoMode(&w, &h); GetAvailableVideoMode(&w, &h);
DEBUG(driver, 1, "SDL: using mode %dx%d", w, h); DEBUG(driver, 1, "SDL: using mode %dx%dx%d", w, h, bpp);
if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
/* Give the application an icon */ /* Give the application an icon */
icon = SDL_CALL SDL_LoadBMP(ICON_DIR PATHSEP "openttd.32.bmp"); icon = SDL_CALL SDL_LoadBMP(ICON_DIR PATHSEP "openttd.32.bmp");
@ -189,14 +198,15 @@ static bool CreateMainSurface(int w, int h)
} }
// DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK // DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK
newscreen = SDL_CALL SDL_SetVideoMode(w, h, 8, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE)); newscreen = SDL_CALL SDL_SetVideoMode(w, h, bpp, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE));
if (newscreen == NULL) if (newscreen == NULL)
return false; return false;
_screen.width = newscreen->w; _screen.width = newscreen->w;
_screen.height = newscreen->h; _screen.height = newscreen->h;
_screen.pitch = newscreen->pitch / sizeof(Pixel); _screen.pitch = newscreen->pitch / (bpp / 8);
_screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
_sdl_screen = newscreen; _sdl_screen = newscreen;
InitPalette(); InitPalette();
@ -469,7 +479,7 @@ static void SdlVideoMainLoop()
(keys[SDLK_DOWN] ? 8 : 0); (keys[SDLK_DOWN] ? 8 : 0);
GameLoop(); GameLoop();
_screen.dst_ptr = (Pixel*)_sdl_screen->pixels; _screen.dst_ptr = _sdl_screen->pixels;
UpdateWindows(); UpdateWindows();
if (++pal_tick > 4) { if (++pal_tick > 4) {
CheckPaletteAnim(); CheckPaletteAnim();
@ -478,7 +488,7 @@ static void SdlVideoMainLoop()
DrawSurfaceToScreen(); DrawSurfaceToScreen();
} else { } else {
SDL_CALL SDL_Delay(1); SDL_CALL SDL_Delay(1);
_screen.dst_ptr = (Pixel*)_sdl_screen->pixels; _screen.dst_ptr = _sdl_screen->pixels;
DrawTextMessage(); DrawTextMessage();
DrawMouseCursor(); DrawMouseCursor();
DrawSurfaceToScreen(); DrawSurfaceToScreen();

View File

@ -9,6 +9,7 @@
#include "../variables.h" #include "../variables.h"
#include "../win32.h" #include "../win32.h"
#include "../window.h" #include "../window.h"
#include "../blitter/blitter.hpp"
#include "win32_v.h" #include "win32_v.h"
#include <windows.h> #include <windows.h>
#include <tchar.h> #include <tchar.h>
@ -16,22 +17,18 @@
static struct { static struct {
HWND main_wnd; HWND main_wnd;
HBITMAP dib_sect; HBITMAP dib_sect;
Pixel *bitmap_bits; void *buffer_bits;
Pixel *buffer_bits;
Pixel *alloced_bits;
HPALETTE gdi_palette; HPALETTE gdi_palette;
int width; int width;
int height; int height;
int width_org; int width_org;
int height_org; int height_org;
bool fullscreen; bool fullscreen;
bool double_size;
bool has_focus; bool has_focus;
bool running; bool running;
} _wnd; } _wnd;
bool _force_full_redraw; bool _force_full_redraw;
bool _double_size;
bool _window_maximize; bool _window_maximize;
uint _display_hz; uint _display_hz;
uint _fullscreen_bpp; uint _fullscreen_bpp;
@ -63,6 +60,10 @@ static void MakePalette()
static void UpdatePalette(HDC dc, uint start, uint count) static void UpdatePalette(HDC dc, uint start, uint count)
{ {
/* We can only update the palette in 8bpp for now */
/* TODO -- We need support for other bpps too! */
if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) return;
RGBQUAD rgb[256]; RGBQUAD rgb[256];
uint i; uint i;
@ -136,11 +137,6 @@ static bool AllocateDibSection(int w, int h);
static void ClientSizeChanged(int w, int h) static void ClientSizeChanged(int w, int h)
{ {
if (_wnd.double_size) {
w /= 2;
h /= 2;
}
// allocate new dib section of the new size // allocate new dib section of the new size
if (AllocateDibSection(w, h)) { if (AllocateDibSection(w, h)) {
// mark all palette colors dirty // mark all palette colors dirty
@ -319,11 +315,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
DrawMouseCursor(); DrawMouseCursor();
} }
if (_wnd.double_size) {
x /= 2;
y /= 2;
}
if (_cursor.fix_at) { if (_cursor.fix_at) {
int dx = x - _cursor.pos.x; int dx = x - _cursor.pos.x;
int dy = y - _cursor.pos.y; int dy = y - _cursor.pos.y;
@ -334,10 +325,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
pt.x = _cursor.pos.x; pt.x = _cursor.pos.x;
pt.y = _cursor.pos.y; pt.y = _cursor.pos.y;
if (_wnd.double_size) {
pt.x *= 2;
pt.y *= 2;
}
ClientToScreen(hwnd, &pt); ClientToScreen(hwnd, &pt);
SetCursorPos(pt.x, pt.y); SetCursorPos(pt.x, pt.y);
} }
@ -400,13 +387,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
* WM_KEYDOWN only handles CTRL+ commands and special keys like VK_LEFT, etc. */ * WM_KEYDOWN only handles CTRL+ commands and special keys like VK_LEFT, etc. */
if (keycode == 0 || (keycode > WKC_PAUSE && GB(keycode, 13, 4) == 0)) return 0; if (keycode == 0 || (keycode > WKC_PAUSE && GB(keycode, 13, 4) == 0)) return 0;
if (keycode == ('D' | WKC_CTRL) && !_wnd.fullscreen) {
_double_size ^= 1;
_wnd.double_size = _double_size;
ClientSizeChanged(_wnd.width, _wnd.height);
MarkWholeScreenDirty();
}
HandleKeypress(0 | (keycode << 16)); HandleKeypress(0 | (keycode << 16));
return 0; return 0;
} }
@ -455,16 +435,8 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
w = r->right - r->left - (r2.right - r2.left); w = r->right - r->left - (r2.right - r2.left);
h = r->bottom - r->top - (r2.bottom - r2.top); h = r->bottom - r->top - (r2.bottom - r2.top);
if (_wnd.double_size) {
w /= 2;
h /= 2;
}
w = clamp(w, 64, MAX_SCREEN_WIDTH); w = clamp(w, 64, MAX_SCREEN_WIDTH);
h = clamp(h, 64, MAX_SCREEN_HEIGHT); h = clamp(h, 64, MAX_SCREEN_HEIGHT);
if (_wnd.double_size) {
w *= 2;
h *= 2;
}
SetRect(&r2, 0, 0, w, h); SetRect(&r2, 0, 0, w, h);
AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
@ -567,8 +539,6 @@ static void MakeWindow(bool full_screen)
{ {
_fullscreen = full_screen; _fullscreen = full_screen;
_wnd.double_size = _double_size && !full_screen;
// recreate window? // recreate window?
if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) { if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
DestroyWindow(_wnd.main_wnd); DestroyWindow(_wnd.main_wnd);
@ -581,6 +551,9 @@ static void MakeWindow(bool full_screen)
if (full_screen) { if (full_screen) {
DEVMODE settings; DEVMODE settings;
/* Make sure we are always at least the screen-depth of the blitter */
if (_fullscreen_bpp < BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) _fullscreen_bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
memset(&settings, 0, sizeof(settings)); memset(&settings, 0, sizeof(settings));
settings.dmSize = sizeof(settings); settings.dmSize = sizeof(settings);
settings.dmFields = settings.dmFields =
@ -649,49 +622,39 @@ static bool AllocateDibSection(int w, int h)
{ {
BITMAPINFO *bi; BITMAPINFO *bi;
HDC dc; HDC dc;
int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
w = clamp(w, 64, MAX_SCREEN_WIDTH); w = clamp(w, 64, MAX_SCREEN_WIDTH);
h = clamp(h, 64, MAX_SCREEN_HEIGHT); h = clamp(h, 64, MAX_SCREEN_HEIGHT);
if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
if (w == _screen.width && h == _screen.height) if (w == _screen.width && h == _screen.height)
return false; return false;
_screen.width = w; _screen.width = w;
_screen.pitch = ALIGN(w, 4); _screen.pitch = ALIGN(w, 4);
_screen.height = h; _screen.height = h;
_screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
if (_wnd.alloced_bits) { if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
free(_wnd.alloced_bits);
_wnd.alloced_bits = NULL;
}
bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if (_wnd.double_size) {
w = ALIGN(w, 4);
_wnd.alloced_bits = _wnd.buffer_bits = (Pixel *)malloc(w * h * sizeof(Pixel));
w *= 2;
h *= 2;
}
bi->bmiHeader.biWidth = _wnd.width = w; bi->bmiHeader.biWidth = _wnd.width = w;
bi->bmiHeader.biHeight = -(_wnd.height = h); bi->bmiHeader.biHeight = -(_wnd.height = h);
bi->bmiHeader.biPlanes = 1; bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = 8; bi->bmiHeader.biBitCount = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
bi->bmiHeader.biCompression = BI_RGB; bi->bmiHeader.biCompression = BI_RGB;
if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect); if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
dc = GetDC(0); dc = GetDC(0);
_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.bitmap_bits, NULL, 0); _wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, NULL, 0);
if (_wnd.dib_sect == NULL) error("CreateDIBSection failed"); if (_wnd.dib_sect == NULL) error("CreateDIBSection failed");
ReleaseDC(0, dc); ReleaseDC(0, dc);
if (!_wnd.double_size) _wnd.buffer_bits = _wnd.bitmap_bits;
return true; return true;
} }
@ -723,7 +686,7 @@ static void FindResolutions()
* Doesn't really matter since we don't pass a string anyways, but still * Doesn't really matter since we don't pass a string anyways, but still
* a letdown */ * a letdown */
for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) { for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) {
if (dm.dmBitsPerPel == 8 && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) && if (dm.dmBitsPerPel == BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) &&
IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)) { IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)) {
uint j; uint j;
@ -786,43 +749,13 @@ static void Win32GdiStop()
#if !defined(WINCE) #if !defined(WINCE)
if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0); if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0);
#endif #endif
if (_wnd.double_size) {
_cur_resolution[0] *= 2;
_cur_resolution[1] *= 2;
}
MyShowCursor(true); MyShowCursor(true);
} }
// simple upscaler by 2
static void filter(int left, int top, int width, int height)
{
uint p = _screen.pitch;
const Pixel *s = _wnd.buffer_bits + top * p + left;
Pixel *d = _wnd.bitmap_bits + top * p * 4 + left * 2;
for (; height > 0; height--) {
int i;
for (i = 0; i != width; i++) {
d[i * 2] = d[i * 2 + 1] = d[i * 2 + p * 2] = d[i * 2 + 1 + p * 2] = s[i];
}
s += p;
d += p * 4;
}
}
static void Win32GdiMakeDirty(int left, int top, int width, int height) static void Win32GdiMakeDirty(int left, int top, int width, int height)
{ {
RECT r = { left, top, left + width, top + height }; RECT r = { left, top, left + width, top + height };
if (_wnd.double_size) {
filter(left, top, width, height);
r.left *= 2;
r.top *= 2;
r.right *= 2;
r.bottom *= 2;
}
InvalidateRect(_wnd.main_wnd, &r, FALSE); InvalidateRect(_wnd.main_wnd, &r, FALSE);
} }

View File

@ -1269,7 +1269,7 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom
x = UnScaleByZoom(vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left; x = UnScaleByZoom(vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left;
y = UnScaleByZoom(vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top; y = UnScaleByZoom(vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top;
vd.dpi.dst_ptr = old_dpi->dst_ptr + x - old_dpi->left + (y - old_dpi->top) * old_dpi->pitch; vd.dpi.dst_ptr = _screen.renderer->MoveTo(old_dpi->dst_ptr, x - old_dpi->left, y - old_dpi->top);
vd.parent_list = parent_list; vd.parent_list = parent_list;
vd.eof_parent_list = endof(parent_list); vd.eof_parent_list = endof(parent_list);

View File

@ -270,7 +270,7 @@ static void DrawOverlappedWindow(Window* const *wz, int left, int top, int right
dp->left = left - (*wz)->left; dp->left = left - (*wz)->left;
dp->top = top - (*wz)->top; dp->top = top - (*wz)->top;
dp->pitch = _screen.pitch; dp->pitch = _screen.pitch;
dp->dst_ptr = _screen.dst_ptr + top * _screen.pitch + left; dp->dst_ptr = _screen.renderer->MoveTo(_screen.dst_ptr, left, top);
dp->zoom = ZOOM_LVL_NORMAL; dp->zoom = ZOOM_LVL_NORMAL;
CallWindowEventNP(*wz, WE_PAINT); CallWindowEventNP(*wz, WE_PAINT);
} }