(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
This commit is contained in:
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
RelativePath=".\..\src\blitter\8bpp_simple.hpp">
</File>
<File
RelativePath=".\..\src\blitter\null.cpp">
</File>
<File
RelativePath=".\..\src\blitter\null.hpp">
</File>
<File
RelativePath=".\..\src\blitter\blitter.hpp">
</File>
@ -996,6 +1002,25 @@
RelativePath=".\..\src\spriteloader\spriteloader.hpp">
</File>
</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
Name="NewGRF"
Filter="">

View File

@ -1527,6 +1527,14 @@
RelativePath=".\..\src\blitter\8bpp_simple.hpp"
>
</File>
<File
RelativePath=".\..\src\blitter\null.cpp"
>
</File>
<File
RelativePath=".\..\src\blitter\null.hpp"
>
</File>
<File
RelativePath=".\..\src\blitter\blitter.hpp"
>
@ -1548,6 +1556,30 @@
>
</File>
</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
Name="NewGRF"
>

View File

@ -297,6 +297,8 @@ blitter/8bpp_optimized.cpp
blitter/8bpp_optimized.hpp
blitter/8bpp_simple.cpp
blitter/8bpp_simple.hpp
blitter/null.cpp
blitter/null.hpp
blitter/blitter.hpp
# Sprite loaders
@ -304,6 +306,13 @@ spriteloader/grf.cpp
spriteloader/grf.hpp
spriteloader/spriteloader.hpp
# Renderer
renderer/8bpp.cpp
renderer/8bpp.hpp
renderer/null.cpp
renderer/null.hpp
renderer/renderer.hpp
# NewGRF
newgrf.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)
{
const byte *src, *src_line;
Pixel8 *dst, *dst_line;
const uint8 *src, *src_line;
uint8 *dst, *dst_line;
/* 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);
dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
src_line = (const uint8 *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
for (int y = 0; y < bp->height; y++) {
dst = dst_line;

View File

@ -7,15 +7,15 @@
#include "blitter.hpp"
typedef Pixel Pixel8;
class Blitter_8bppDebug : public Blitter {
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> {

View File

@ -12,16 +12,16 @@ static FBlitter_8bppOptimized iFBlitter_8bppOptimized;
void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{
const byte *src, *src_next;
Pixel8 *dst, *dst_line;
const uint8 *src, *src_next;
uint8 *dst, *dst_line;
uint offset = 0;
/* 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 */
src = (const byte *)bp->sprite + offset;
dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
src = (const uint8 *)bp->sprite + offset;
dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
/* Skip over the top lines in the source image */
for (int y = 0; y < bp->skip_top; y++) {

View File

@ -7,15 +7,15 @@
#include "blitter.hpp"
typedef Pixel Pixel8;
class Blitter_8bppOptimized : public Blitter {
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> {

View File

@ -11,12 +11,12 @@ static FBlitter_8bppSimple iFBlitter_8bppSimple;
void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{
const byte *src, *src_line;
Pixel8 *dst, *dst_line;
const uint8 *src, *src_line;
uint8 *dst, *dst_line;
/* 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);
dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
src_line = (const uint8 *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
for (int y = 0; y < bp->height; y++) {
dst = dst_line;

View File

@ -7,15 +7,15 @@
#include "blitter.hpp"
typedef Pixel Pixel8;
class Blitter_8bppSimple : public Blitter {
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> {

View File

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

24
src/blitter/null.cpp Normal file
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;
}

30
src/blitter/null.hpp Normal file
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;
static FontSize _last_fontsize;
static Pixel _cursor_backup[64 * 64];
static uint8 _cursor_backup[64 * 64 * 4];
static Rect _invalid_rect;
static const byte *_color_remap_ptr;
static byte _string_colorremap[3];
@ -58,37 +58,20 @@ static byte _string_colorremap[3];
#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64)
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)
{
const Pixel *src;
Pixel *dst;
int p;
int ht;
const void *src;
void *dst;
if (xo == 0 && yo == 0) return;
if (_cursor.visible) UndrawMouseCursor();
UndrawTextMessage();
p = _screen.pitch;
if (yo > 0) {
/*Calculate pointers */
dst = _screen.dst_ptr + (top + height - 1) * p + left;
src = dst - yo * p;
dst = _screen.renderer->MoveTo(_screen.dst_ptr, left, top + height - 1);
src = _screen.renderer->MoveTo(dst, 0, -yo);
/* Decrease height and increase top */
top += yo;
@ -97,23 +80,20 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
/* Adjust left & width */
if (xo >= 0) {
dst += xo;
dst = _screen.renderer->MoveTo(dst, xo, 0);
left += xo;
width -= xo;
} else {
src -= xo;
src = _screen.renderer->MoveTo(src, -xo, 0);
width += xo;
}
for (ht = height; ht > 0; --ht) {
memcpy(dst, src, width * sizeof(Pixel));
src -= p;
dst -= p;
}
/* Negative height as we want to copy from bottom to top */
_screen.renderer->CopyFromBuffer(dst, src, width, -height, _screen.pitch);
} else {
/* Calculate pointers */
dst = _screen.dst_ptr + top * p + left;
src = dst - yo * p;
dst = _screen.renderer->MoveTo(_screen.dst_ptr, left, top);
src = _screen.renderer->MoveTo(dst, 0, -yo);
/* Decrese height. (yo is <=0). */
height += yo;
@ -121,21 +101,17 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
/* Adjust left & width */
if (xo >= 0) {
dst += xo;
dst = _screen.renderer->MoveTo(dst, xo, 0);
left += xo;
width -= xo;
} else {
src -= xo;
src = _screen.renderer->MoveTo(src, -xo, 0);
width += xo;
}
/* the y-displacement may be 0 therefore we have to use memmove,
* because source and destination may overlap */
for (ht = height; ht > 0; --ht) {
memmove(dst, src, width * sizeof(Pixel));
src += p;
dst += p;
}
_screen.renderer->MoveBuffer(dst, src, width, height);
}
/* This part of the screen is now dirty. */
_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)
{
const DrawPixelInfo* dpi = _cur_dpi;
Pixel *dst;
const DrawPixelInfo *dpi = _cur_dpi;
void *dst;
const int otop = top;
const int oleft = left;
@ -166,40 +142,37 @@ void GfxFillRect(int left, int top, int right, int bottom, int color)
bottom -= top;
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, USE_COLORTABLE)) {
do {
memset(dst, color, right * sizeof(Pixel));
dst += dpi->pitch;
_screen.renderer->SetHorizontalLine(dst, right, (uint8)color);
dst = _screen.renderer->MoveTo(dst, 0, 1);
} while (--bottom);
} else {
/* use colortable mode */
const byte* ctab = GetNonSprite(GB(color, 0, PALETTE_WIDTH)) + 1;
do {
int i;
for (i = 0; i != right; i++) dst[i] = ctab[dst[i]];
dst += dpi->pitch;
for (int i = 0; i != right; i++) _screen.renderer->SetPixel(dst, i, 0, ctab[((uint8 *)dst)[i]]);
dst = _screen.renderer->MoveTo(dst, 0, 1);
} while (--bottom);
}
} else {
byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
do {
int i;
for (i = (bo ^= 1); i < right; i += 2) dst[i] = (byte)color;
dst += dpi->pitch;
for (int i = (bo ^= 1); i < right; i += 2) _screen.renderer->SetPixel(dst, i, 0, (uint8)color);
dst = _screen.renderer->MoveTo(dst, 0, 1);
} while (--bottom > 0);
}
}
static void GfxSetPixel(int x, int y, int color)
{
const DrawPixelInfo* dpi = _cur_dpi;
if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top)<0 || y >= dpi->height)
return;
dpi->dst_ptr[y * dpi->pitch + x] = color;
const DrawPixelInfo *dpi = _cur_dpi;
if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top) < 0 || y >= dpi->height) return;
_screen.renderer->SetPixel(dpi->dst_ptr, x, y, 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)
uint i;
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];
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_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) {
_cursor.visible = false;
memcpy_pitch(
_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);
_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);
_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_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 */
memcpy_pitch(
_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);
_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);
/* Draw cursor on screen */
_cur_dpi = &_screen;
@ -1233,7 +1208,8 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int heigh
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) {
height = o->height - top;

View File

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

View File

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

71
src/renderer/8bpp.cpp Normal file
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;
}

29
src/renderer/8bpp.hpp Normal file
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 */

39
src/renderer/null.cpp Normal file
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;
}

29
src/renderer/null.hpp Normal file
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 */

165
src/renderer/renderer.hpp Normal file
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 "date.h"
#include "helpers.hpp"
#include "blitter/blitter.hpp"
#include "fileio.h"
char _screenshot_format_name[8];
@ -22,7 +23,7 @@ uint _cur_screenshot_format;
ScreenshotType current_screenshot_type;
/* 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);
struct ScreenshotFormat {
@ -72,10 +73,11 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
FILE *f;
uint i, padw;
uint n, maxlines;
uint pal_size = 0;
uint bpp = pixelformat / 8;
/* only implemented for 8bit images so far. */
if (pixelformat != 8)
return false;
/* only implemented for 8bit and 32bit images so far. */
if (pixelformat != 8 && pixelformat != 32) return false;
f = fopen(name, "wb");
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 */
padw = ALIGN(w, 4);
if (pixelformat == 8) pal_size = sizeof(RgbQuad) * 256;
/* setup the file header */
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.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 */
bih.size = TO_LE32(sizeof(BitmapInfoHeader));
bih.width = TO_LE32(w);
bih.height = TO_LE32(h);
bih.planes = TO_LE16(1);
bih.bitcount = TO_LE16(8);
bih.bitcount = TO_LE16(pixelformat);
bih.compression = 0;
bih.sizeimage = 0;
bih.xpels = 0;
@ -102,24 +106,26 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
bih.clrused = 0;
bih.clrimp = 0;
/* convert the palette to the windows format */
for (i = 0; i != 256; i++) {
rq[i].red = palette[i].r;
rq[i].green = palette[i].g;
rq[i].blue = palette[i].b;
rq[i].reserved = 0;
if (pixelformat == 8) {
/* convert the palette to the windows format */
for (i = 0; i != 256; i++) {
rq[i].red = palette[i].r;
rq[i].green = palette[i].g;
rq[i].blue = palette[i].b;
rq[i].reserved = 0;
}
}
/* write file header and info header and palette */
if (fwrite(&bfh, sizeof(bfh), 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 */
maxlines = clamp(65536 / padw, 16, 128);
/* 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) {
fclose(f);
return false;
@ -137,7 +143,7 @@ static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *user
/* write each line */
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);
fclose(f);
return false;
@ -173,12 +179,12 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
FILE *f;
uint i, y, n;
uint maxlines;
uint bpp = pixelformat / 8;
png_structp png_ptr;
png_infop info_ptr;
/* only implemented for 8bit images so far. */
if (pixelformat != 8)
return false;
/* only implemented for 8bit and 32bit images so far. */
if (pixelformat != 8 && pixelformat != 32) return false;
f = fopen(name, "wb");
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_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);
/* convert the palette to the .PNG format. */
for (i = 0; i != 256; i++) {
rq[i].red = palette[i].r;
rq[i].green = palette[i].g;
rq[i].blue = palette[i].b;
if (pixelformat == 8) {
/* convert the palette to the .PNG format. */
for (i = 0; i != 256; i++) {
rq[i].red = palette[i].r;
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_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 */
maxlines = clamp(65536 / w, 16, 128);
/* 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) {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(f);
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;
do {
@ -244,7 +272,7 @@ static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *user
/* write them to png */
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);
png_write_end(png_ptr, info_ptr);
@ -288,6 +316,10 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
PcxHeader pcx;
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)
return false;
@ -321,7 +353,7 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
maxlines = clamp(65536 / w, 16, 128);
/* 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) {
fclose(f);
return false;
@ -340,14 +372,14 @@ static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *user
/* write them to pcx */
for (i = 0; i != n; i++) {
const Pixel* bufp = buff + i * w;
const uint8 *bufp = buff + i * w;
byte runchar = bufp[0];
uint runcount = 1;
uint j;
/* for each pixel... */
for (j = 1; j < w; j++) {
Pixel ch = bufp[j];
uint8 ch = bufp[j];
if (ch != runchar || runcount >= 0x3f) {
if (runcount > 1 || (runchar & 0xC0) == 0xC0)
@ -447,17 +479,14 @@ void SetScreenshotFormat(int i)
}
/* 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) {
memcpy(buf, _screen.dst_ptr + y * _screen.pitch, _screen.width * sizeof(Pixel));
++y;
buf += pitch;
}
void *src = _screen.renderer->MoveTo(_screen.dst_ptr, 0, y);
_screen.renderer->CopyToBuffer(src, buf, _screen.width, n, pitch);
}
/* 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;
DrawPixelInfo dpi, *old_dpi;
@ -534,7 +563,7 @@ bool IsScreenshotRequested()
static bool MakeSmallScreenshot()
{
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()
@ -553,7 +582,7 @@ static bool MakeWorldScreenshot()
vp.height = vp.virtual_height;
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()

View File

@ -1225,14 +1225,13 @@ static const SettingDesc _music_settings[] = {
/* win32_v.c only settings */
#ifdef WIN32
extern bool _force_full_redraw, _double_size, _window_maximize;
extern bool _force_full_redraw, _window_maximize;
extern uint _display_hz, _fullscreen_bpp;
static const SettingDescGlobVarList _win32_settings[] = {
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_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_END()
};

View File

@ -167,41 +167,23 @@ static const LegendAndColour * const _legend_table[] = {
_legend_land_owners,
};
#if defined(OTTD_ALIGNMENT)
static inline void WRITE_PIXELS(Pixel* d, uint32 val)
{
# if defined(TTD_BIG_ENDIAN)
d[0] = GB(val, 24, 8);
d[1] = GB(val, 16, 8);
d[2] = GB(val, 8, 8);
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
}
static inline void WRITE_PIXELS(void *d, uint32 val)
{
uint8 *val8 = (uint8 *)&val;
_screen.renderer->SetPixel(d, 0, 0, val8[0]);
_screen.renderer->SetPixel(d, 1, 0, val8[1]);
_screen.renderer->SetPixel(d, 2, 0, val8[2]);
_screen.renderer->SetPixel(d, 3, 0, val8[3]);
}
/* need to use OR, otherwise we will overwrite the wrong pixels at the edges :( */
static inline void WRITE_PIXELS_OR(Pixel *d, uint32 val)
{
# if defined(TTD_BIG_ENDIAN)
d[0] |= GB(val, 24, 8);
d[1] |= GB(val, 16, 8);
d[2] |= GB(val, 8, 8);
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
static inline void WRITE_PIXELS_OR(void *d, uint32 val)
{
uint8 *val8 = (uint8 *)&val;
_screen.renderer->SetPixelIfEmpty(d, 0, 0, val8[0]);
_screen.renderer->SetPixelIfEmpty(d, 1, 0, val8[1]);
_screen.renderer->SetPixelIfEmpty(d, 2, 0, val8[2]);
_screen.renderer->SetPixelIfEmpty(d, 3, 0, val8[3]);
}
#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
* @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 {
/* 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);
}
/* 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;
int dx,dy, x, y, x2, y2;
Pixel *ptr;
void *ptr;
int tile_x;
int tile_y;
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;
y = 0;
@ -609,7 +591,6 @@ static void DrawSmallMap(DrawPixelInfo *dpi, Window *w, int type, bool show_town
/* number of lines */
reps = (dpi->height - y + 1) / 2;
if (reps > 0) {
// assert(ptr >= dpi->dst_ptr);
DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]);
}
@ -617,13 +598,13 @@ skip_column:
if (y == 0) {
tile_y++;
y++;
ptr += dpi->pitch;
ptr = _screen.renderer->MoveTo(ptr, 0, 1);
} else {
tile_x--;
y--;
ptr -= dpi->pitch;
ptr = _screen.renderer->MoveTo(ptr, 0, -1);
}
ptr += 2;
ptr = _screen.renderer->MoveTo(ptr, 2, 0);
x += 2;
}
@ -666,12 +647,11 @@ skip_column:
}
/* Calculate pointer to pixel and the color */
ptr = dpi->dst_ptr + y * dpi->pitch + x;
color = (type == 1) ? _vehicle_type_colors[v->type] : 0xF;
/* And draw either one or two pixels depending on clipping */
ptr[0] = color;
if (!skip) ptr[1] = color;
_screen.renderer->SetPixel(dpi->dst_ptr, x, y, 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 left and pixels from the bottom. The height is the maximum height */
static const Oblong _textmsg_box = {10, 30, 500, 150};
static Pixel _textmessage_backup[150 * 500]; // (height * width)
extern void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch);
static uint8 _textmessage_backup[150 * 500 * 4]; // (height * width)
static inline uint GetTextMessageCount()
{
@ -163,11 +161,7 @@ void UndrawTextMessage()
_textmessage_visible = false;
/* Put our 'shot' back to the screen */
memcpy_pitch(
_screen.dst_ptr + x + y * _screen.pitch,
_textmessage_backup,
width, height, _textmsg_box.width, _screen.pitch);
_screen.renderer->CopyFromBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, x, y), _textmessage_backup, width, height, _textmsg_box.width);
/* And make sure it is updated next time */
_video_driver->make_dirty(x, y, width, height);
@ -227,10 +221,7 @@ void DrawTextMessage()
if (width <= 0 || height <= 0) return;
/* Make a copy of the screen as it is before painting (for undraw) */
memcpy_pitch(
_textmessage_backup,
_screen.dst_ptr + x + y * _screen.pitch,
width, height, _screen.pitch, _textmsg_box.width);
_screen.renderer->CopyToBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, x, y), _textmessage_backup, width, height, _textmsg_box.width);
_cur_dpi = &_screen; // switch to _screen painting

View File

@ -69,6 +69,7 @@ extern "C" void HideMenuBar();
#include "../macros.h"
#include "../os/macosx/splash.h"
#include "../variables.h"
#include "../blitter/blitter.hpp"
#include "cocoa_v.h"
#include "cocoa_keys.h"
@ -950,6 +951,10 @@ static void QZ_SetPortAlphaOpaque()
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;
switch (_cocoa_video_data.device_bpp) {

View File

@ -13,6 +13,7 @@
#include "../console.h"
#include "../variables.h"
#include "../genworld.h"
#include "../blitter/blitter.hpp"
#include "dedicated_v.h"
#ifdef BEOS_NET_SERVER
@ -112,7 +113,7 @@ static void CloseWindowsConsoleThread()
#endif
static Pixel *_dedicated_video_mem;
static void *_dedicated_video_mem;
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
extern void SwitchMode(int new_mode);
@ -120,9 +121,14 @@ extern void SwitchMode(int new_mode);
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.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");

View File

@ -5,19 +5,23 @@
#include "../gfx.h"
#include "../variables.h"
#include "../window.h"
#include "../debug.h"
#include "../blitter/blitter.hpp"
#include "null_v.h"
static Pixel *_null_video_mem = NULL;
static const char* NullVideoStart(const char* const* parm)
{
_screen.width = _screen.pitch = _cur_resolution[0];
_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;
}
static void NullVideoStop() { free(_null_video_mem); }
static void NullVideoStop() { }
static void NullVideoMakeDirty(int left, int top, int width, int height) {}
@ -27,7 +31,7 @@ static void NullVideoMainLoop()
for (i = 0; i < 1000; i++) {
GameLoop();
_screen.dst_ptr = _null_video_mem;
_screen.dst_ptr = NULL;
UpdateWindows();
}
}

View File

@ -13,6 +13,8 @@
#include "../window.h"
#include "../network/network.h"
#include "../variables.h"
#include "../blitter/blitter.hpp"
#include "../renderer/renderer.hpp"
#include "sdl_v.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)
{
/* 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];
uint i;
@ -172,10 +178,13 @@ static bool CreateMainSurface(int w, int h)
extern const char _openttd_revision[];
SDL_Surface *newscreen, *icon;
char caption[50];
int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
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 */
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
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)
return false;
_screen.width = newscreen->w;
_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;
InitPalette();
@ -469,7 +479,7 @@ static void SdlVideoMainLoop()
(keys[SDLK_DOWN] ? 8 : 0);
GameLoop();
_screen.dst_ptr = (Pixel*)_sdl_screen->pixels;
_screen.dst_ptr = _sdl_screen->pixels;
UpdateWindows();
if (++pal_tick > 4) {
CheckPaletteAnim();
@ -478,7 +488,7 @@ static void SdlVideoMainLoop()
DrawSurfaceToScreen();
} else {
SDL_CALL SDL_Delay(1);
_screen.dst_ptr = (Pixel*)_sdl_screen->pixels;
_screen.dst_ptr = _sdl_screen->pixels;
DrawTextMessage();
DrawMouseCursor();
DrawSurfaceToScreen();

View File

@ -9,6 +9,7 @@
#include "../variables.h"
#include "../win32.h"
#include "../window.h"
#include "../blitter/blitter.hpp"
#include "win32_v.h"
#include <windows.h>
#include <tchar.h>
@ -16,22 +17,18 @@
static struct {
HWND main_wnd;
HBITMAP dib_sect;
Pixel *bitmap_bits;
Pixel *buffer_bits;
Pixel *alloced_bits;
void *buffer_bits;
HPALETTE gdi_palette;
int width;
int height;
int width_org;
int height_org;
bool fullscreen;
bool double_size;
bool has_focus;
bool running;
} _wnd;
bool _force_full_redraw;
bool _double_size;
bool _window_maximize;
uint _display_hz;
uint _fullscreen_bpp;
@ -63,6 +60,10 @@ static void MakePalette()
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];
uint i;
@ -136,11 +137,6 @@ static bool AllocateDibSection(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
if (AllocateDibSection(w, h)) {
// mark all palette colors dirty
@ -319,11 +315,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
DrawMouseCursor();
}
if (_wnd.double_size) {
x /= 2;
y /= 2;
}
if (_cursor.fix_at) {
int dx = x - _cursor.pos.x;
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.y = _cursor.pos.y;
if (_wnd.double_size) {
pt.x *= 2;
pt.y *= 2;
}
ClientToScreen(hwnd, &pt);
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. */
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));
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);
h = r->bottom - r->top - (r2.bottom - r2.top);
if (_wnd.double_size) {
w /= 2;
h /= 2;
}
w = clamp(w, 64, MAX_SCREEN_WIDTH);
h = clamp(h, 64, MAX_SCREEN_HEIGHT);
if (_wnd.double_size) {
w *= 2;
h *= 2;
}
SetRect(&r2, 0, 0, w, h);
AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
@ -567,8 +539,6 @@ static void MakeWindow(bool full_screen)
{
_fullscreen = full_screen;
_wnd.double_size = _double_size && !full_screen;
// recreate window?
if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
DestroyWindow(_wnd.main_wnd);
@ -581,6 +551,9 @@ static void MakeWindow(bool full_screen)
if (full_screen) {
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));
settings.dmSize = sizeof(settings);
settings.dmFields =
@ -649,49 +622,39 @@ static bool AllocateDibSection(int w, int h)
{
BITMAPINFO *bi;
HDC dc;
int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
w = clamp(w, 64, MAX_SCREEN_WIDTH);
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)
return false;
_screen.width = w;
_screen.pitch = ALIGN(w, 4);
_screen.height = h;
if (_wnd.alloced_bits) {
free(_wnd.alloced_bits);
_wnd.alloced_bits = 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());
bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
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.biHeight = -(_wnd.height = h);
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = 8;
bi->bmiHeader.biBitCount = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
bi->bmiHeader.biCompression = BI_RGB;
if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
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");
ReleaseDC(0, dc);
if (!_wnd.double_size) _wnd.buffer_bits = _wnd.bitmap_bits;
return true;
}
@ -723,7 +686,7 @@ static void FindResolutions()
* Doesn't really matter since we don't pass a string anyways, but still
* a letdown */
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)) {
uint j;
@ -786,43 +749,13 @@ static void Win32GdiStop()
#if !defined(WINCE)
if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0);
#endif
if (_wnd.double_size) {
_cur_resolution[0] *= 2;
_cur_resolution[1] *= 2;
}
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)
{
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);
}

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;
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.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->top = top - (*wz)->top;
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;
CallWindowEventNP(*wz, WE_PAINT);
}