1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
|
// -----------------------------------------------------------------------------
// This file is part of Broken Sword 2.5
// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsd�rfer
//
// Broken Sword 2.5 is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Broken Sword 2.5 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Broken Sword 2.5; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// -----------------------------------------------------------------------------
/*
BS_GraphicEngine
----------------
Dies ist das Graphik-Engine Interface, dass alle Methoden und Klassen enth�lt, die eine
Graphik-Engine implementieren muss.
Autor: Malte Thiesen
*/
#ifndef SWORD25_GRAPHICENGINE_H
#define SWORD25_GRAPHICENGINE_H
// Includes
#include "sword25/kernel/memlog_off.h"
#include <vector>
#include "sword25/kernel/memlog_on.h"
#include "sword25/kernel/common.h"
#include "sword25/kernel/bs_stdint.h"
#include "sword25/kernel/resservice.h"
#include "sword25/kernel/persistable.h"
#include "sword25/math/rect.h"
#include "sword25/gfx/framecounter.h"
#include "sword25/gfx/renderobjectptr.h"
class BS_Kernel;
class BS_Image;
class BS_Panel;
class BS_Screenshot;
// Typen
typedef unsigned int BS_COLOR;
// Makros
#define BS_RGB(R,G,B) (0xFF000000 | ((R) << 16) | ((G) << 8) | (B))
#define BS_ARGB(A,R,G,B) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B))
/**
@brief Dies ist das Graphik-Engine Interface, dass alle Methoden und Klassen enth�lt, die eine Graphik-Engine implementieren muss.
Hier sind nur wenige Rumpffunktionen realisiert, wie z.B. das Abfragen der Parameter des Ausgabepuffers.
Die Hauptfunktionen muss eine Implementation dieses Inferfaces stellen.<br>
Die bisher einzige Implementation ist BS_DDrawGfx.
*/
class BS_GraphicEngine : public BS_ResourceService, public BS_Persistable
{
public:
// Enums
// -----
// Farbformate
/**
@brief Die von der Engine benutzten Farbformate
*/
enum COLOR_FORMATS
{
/// Undefiniertes/unbekanntes Farbformat
CF_UNKNOWN = 0,
/// 16 Bit Farbformat (5 Bit Rot, 5 Bit Gr�n, 5 Bit Blau)
CF_RGB15,
/// 16 Bit Farbformat (5 Bit Rot, 6 Bit Gr�n, 5 Bit Blau)
CF_RGB16,
/**
Spezielles Alpha-Farbformat der Engine, welches besonders schnelles Darstellen unter Benutzung von MMX-Befehlen unterst�tzt.<br>
Die Pixel sind 16 Bit breit und haben das selbe Format wie #CF_RGB15. Zus�tzlich besitzt jeder Pixel noch einen 8 Bit Alphawert.<br>
Es werden jeweils 4 Pixel und 4 Alphawerte zu einem 12 Byte gro�en Datenblock zusammengefasst.<br>
Dabei werden die Daten in folgender Reihenfolge abgelegt:
Alpha0 Alpha1 Alpha2 Alpha3 Pixel0 Pixel1 Pixel2 Pixel3
Falls die Pixelanzahl einer Zeile nicht durch 4 teilbar ist, wird der letzte Pixelblock trotzdem komplett abgespeichert, die
nicht verwendeten Pixel- und Alphawerte k�nnen beliebige Werte haben.
*/
CF_RGB15_INTERLEAVED,
/**
Spezielles Alpha-Farbformat der Engine, welches besonders schnelles Darstellen unter Benutzung von MMX-Befehlen unterst�tzt.<br>
Die Pixel sind 16 Bit breit und haben das selbe Format wie #CF_RGB16. Zus�tzlich besitzt jeder Pixel noch einen 8 Bit Alphawert.<br>
Es werden jeweils 4 Pixel und 4 Alphawerte zu einem 12 Byte gro�en Datenblock zusammengefasst.<br>
Dabei werden die Daten in folgender Reihenfolge abgelegt:
Alpha0 Alpha1 Alpha2 Alpha3 Pixel0 Pixel1 Pixel2 Pixel3
Falls die Pixelanzahl einer Zeile nicht durch 4 teilbar ist, wird der letzte Pixelblock trotzdem komplett abgespeichert, die
nicht verwendeten Pixel- und Alphawerte k�nnen beliebige Werte haben.
*/
CF_RGB16_INTERLEAVED,
/**
24 Bit Farbformat (8 Bit Rot, 8 Bit Gr�n, 8 Bit Blau)
*/
CF_RGB24,
/**
32 Bit Farbformat (8 Bit Alpha, 8 Bit Rot, 8 Bit Gr�n, 8 Bit Blau) (little endian)
*/
CF_ARGB32,
/**
32 Bit Farbformat (8 Bit Alpha, 8 Bit Blau, 8 Bit Gr�n, 8 Bit Rot) (little endian)
*/
CF_ABGR32
};
// Interface
// ---------
/**
@brief Initialisiert die Graphikengine und setzt den Bildschirmmodus.
@param Width die Breite des Ausgabepuffers in Pixeln.<br>Der Standardwert ist 800.
@param Height die H�he des Ausgabepuffers in Pixeln.<br>Der Standardwert ist 600.
@param BitDepth die Bittiefe des gew�nschten Ausgabepuffers in Bit.<br>Der Standardwert ist 16.
@param BackbufferCount die Anzahl an Backbuffern die erzeugt werden soll.<br>Der Standardwert ist 2.
@param Windowed gibt an, ob die Engine im Fenstermodus laufen soll. Falls true angegeben wird, wird ein Fenster ge�ffnet in das
die Ausgaben gerendert werden. Ansonsten wird ein Vollbildmodus gesetzt der den Parametern das Ausgabepuffers
entspricht.
@return Gibt false zur�ck, falls die Initialisierung fehlgeschlagen ist.
@remark Der Fenstermodus sollte nur zu Debuggingzwecken benutzt werden und ist nicht daf�r gedacht im endg�ltigen Produkt benutzt
zu werden.
@remark Diese Methode sollte direkt nach der Initialisierung aller Services aufgerufen werden.
*/
virtual bool Init(int Width = 800, int Height = 600, int BitDepth = 16, int BackbufferCount = 2, bool Windowed = false) = 0;
//@{
/** @name Frame-Methoden */
/**
@brief Beginnt das Rendern eines neuen Frames.
@param UpdateAll gibt an, ob der Renderer im n�chsten Frame alles neu zeichnen soll.<br>
Diese Funktion kann n�tzlich sein, wenn der Renderer mit Dirty-Rectangles arbeitet, der Benutzer aber gelegentlich
darauf angewiesen ist, dass der gesamte Bildschirminhalt neu gezeichnet werden soll.<br>
Der Standardwert ist false.
Diese Methode muss am Anfang das Main-Loops aufgerufen werden und vor dem Aufruf jeglicher Rendermethoden.
@return Gibt false zur�ck, falls ein Fehler aufgetreten ist.
@remark Implementationen dieser Methode m�ssen _UpdateLastFrameDuration() aufrufen.
*/
virtual bool StartFrame(bool UpdateAll = false) = 0;
/**
@brief Beendet das Rendern des Frames und stellt diesen auf dem Bildschirm dar.
Diese Methode muss am Ende des Main-Loops aufgerufen werden. Nach dem Aufruf d�rfen keine weiteren Rendermethoden mehr aufgerufen
werden. Daf�r muss erst wieder ein Aufruf von #StartFrame erfolgen.
@return Gibt false zur�ck, falls ein Fehler aufgetreten ist:
*/
virtual bool EndFrame() = 0;
//@}
//@{
/** @name Debug-Methoden */
/**
@brief Zeichnet eine Line in den Framebuffer.
Diese Methode muss zwischen StartFrame() und EndFrame() aufgerufen werden und ist nur f�r Debugzwecke gedacht.
Die Linie erscheint nur f�r einen Frame. Wenn die Linie dauerhaft zu sehen sein soll, muss sie jeden Frame neu
gezeichnet werden.
@param Start der Startpunkt der Linie
@param End der Endpunkt der Linie
@param Color die Farbe der Linie. Der Standardwert ist BS_RGB(255, 255, 255) (Wei�).
*/
virtual void DrawDebugLine(const BS_Vertex & Start, const BS_Vertex & End, unsigned int Color = BS_RGB(255, 255, 255)) = 0;
/**
@brief Erstellt einen Screenshot.
Erstellt einen Screenshot vom aktuellen Framebuffer und schreibt ihn in eine Grafikdatei.<br>
Das verwendete Dateiformat ist PNG.
@param Der Dateiname des Screenshots.
@return Gibt true zur�ck, wenn der Screenshot gespeichert werden konnte, ansonsten false.
@remark Diese Methode darf erst nach einem Aufruf von EndFrame() und vor dem n�chsten Aufruf von StartFrame() aufgerufen werden.
*/
bool SaveScreenshot(const std::string & Filename);
/**
@Brief Erstellt einen kleinen Screenshot.
Erstellt einen Screenshot mit den Ma�en 200x125. Hierf�r werden am oberen und unteren Bildschirmrand die Interfaceleisten abgeschnitten und
das Bild auf ein 16tel seiner Ursprungsgr��e verkleinert.
@param Der Dateiname des Screenshots.
@return Gibt true zur�ck, wenn der Screenshot gespeichert werden konnte, ansonsten false.
@remark Diese Methode darf erst nach einem Aufruf von EndFrame() und vor dem n�chsten Aufruf von StartFrame() aufgerufen werden.
@remark Der Framebuffer muss eine Aufl�sung von 800x600 haben.
*/
bool SaveThumbnailScreenshot(const std::string & Filename);
/**
@brief Liest den aktuellen Inhalt des Framebuffer aus.
@param Width enth�lt nach einem erfolgreichen Aufruf die Breite des Framebuffers.
@param Height enth�lt nach einem erfolgreichen Aufruf die H�he des Framebuffers.
@param Data enth�lt nach einem erfolgreichen Aufruf den Inhalt des Framebuffers als 32-Bit Farbwerte.
@return Gibt true zur�ck, wenn der Aufruf erfolgreich war, ansonsten false.
@remark Diese Methode ist f�r das Erstellen von Screenshots gedacht. Sie muss also nicht sehr effizient sein.
@remark Diese Methode darf erst nach einem Aufruf von EndFrame() und vor dem n�chsten Aufruf von StartFrame() aufgerufen werden.
*/
virtual bool GetScreenshot(unsigned int & Width, unsigned int & Height, std::vector<unsigned int> & Data) = 0;
//@}
virtual BS_RenderObjectPtr<BS_Panel> GetMainPanel() = 0;
/**
@brief Gibt die Zeit (in Microsekunden) zur�ck die seit dem letzten Frame vergangen ist.
*/
int GetLastFrameDurationMicro() { if (m_TimerActive) return m_LastFrameDuration; else return 0; }
/**
@brief Gibt die Zeit (in Sekunden) zur�ck die seit dem letzten Frame vergangen ist.
*/
float GetLastFrameDuration() { if (m_TimerActive) return static_cast<float>(m_LastFrameDuration) / 1000000.0f; else return 0; }
void StopMainTimer() { m_TimerActive = false; }
void ResumeMainTimer() { m_TimerActive = true; }
float GetSecondaryFrameDuration() { return static_cast<float>(m_LastFrameDuration) / 1000000.0f; }
//@{
/** @name Accessor-Methoden */
/**
@brief Gibt die Breite des Ausgabepuffers in Pixeln zur�ck.
*/
int GetDisplayWidth() { return m_Width; }
/**
@brief Gibt die H�he des Ausgabepuffers in Pixeln zur�ck.
*/
int GetDisplayHeight() { return m_Height; }
/**
@brief Gibt die Bounding-Box des Ausgabepuffers zur�ck. (0, 0, Width, Height)
*/
BS_Rect& GetDisplayRect() { return m_ScreenRect; }
/**
@brief Gibt die Bittiefe des Ausgabepuffers zur�ck.
*/
int GetBitDepth() { return m_BitDepth; }
/**
@brief Legt fest ob der Framebufferwechsel mit dem vertikalen Strahlenr�cklauf synchronisiert werden soll.<br>
Vsync ist standardm��ig eingeschaltet.
@param Vsync gibt an, ob der Framebufferwechsel mit dem vertikalen Strahlenr�cklauf synchronisiert werden soll.
@remark Im Fenstermodus hat diese Einstellung keine Auswirkung.
*/
virtual void SetVsync(bool Vsync) = 0;
/**
@brief Gibt true zur�ck, wenn V-Sync an ist.
@remark Im Fenstermodus hat diese Einstellung keine Auswirkung.
*/
virtual bool GetVsync() const = 0;
/**
@brief Gibt true zur�ck, falls die Engine im Fenstermodus l�uft.
*/
bool IsWindowed() { return m_Windowed; }
/**
@brief F�llt einen Rechteckigen Bereich des Framebuffers mit einer Farbe.
@param FillRectPtr Pointer auf ein BS_Rect, welches den Ausschnitt des Framebuffers spezifiziert, der gef�llt
werden soll oder 0, falls das gesamte Bild gef�llt werden soll.<br>
Der Standardwert ist 0.
@param Color der 32 Bit Farbwert mit dem der Bildbereich gef�llt werden soll.<br>
Der Standardwert ist BS_RGB(0, 0, 0) (Schwarz).
@return Gibt true zur�ck, wenn der Aufruf erfolgreich war, ansonsten false.
@remark Es ist m�glich �ber die Methode transparente Rechtecke darzustellen, indem man eine Farbe mit einem
Alphawert ungleich 255 angibt.
@remark Falls das Rechteck nicht v�llig innerhalb des Bildschirms ist, wird es automatisch zurechtgestutzt.
*/
virtual bool Fill(const BS_Rect * FillRectPtr = 0, unsigned int Color = BS_RGB(0, 0, 0)) = 0;
//@}
//@{
/** @name Debugging-Methoden */
int GetFPSCount() const { return m_FPSCounter.GetFPS(); }
int GetRepaintedPixels() const { return m_RepaintedPixels; }
//@}
//@{
/** @name Auskunfts-Methoden */
/**
@brief Gibt die Gr��e eines Pixeleintrages in Byte f�r ein bestimmtes Farbformat zur�ck
@param ColorFormat das gew�nschte Farbformat. Der Parameter muss vom Typ COLOR_FORMATS sein.
@return Gibt die Gr��e eines Pixeleintrages in Byte des Farbsformates ColorFormat zur�ck.<br>
Falls das Farbformat unbekannt ist, wird -1 zur�ckgegeben.
*/
static int GetPixelSize(BS_GraphicEngine::COLOR_FORMATS ColorFormat)
{
switch (ColorFormat)
{
case BS_GraphicEngine::CF_RGB16:
case BS_GraphicEngine::CF_RGB15:
return 2;
case BS_GraphicEngine::CF_RGB16_INTERLEAVED:
case BS_GraphicEngine::CF_RGB15_INTERLEAVED:
return 3;
case BS_GraphicEngine::CF_ARGB32:
return 4;
}
return -1;
}
/**
@brief Berechnet die L�nge einer Bildzeile eines Bilder in Byte, abh�ngig vom Farbformat.
@param ColorFormat das Farbformat des Bildes.
@param Width die L�nge einer Bildzeile in Pixel.
@return Gibt die L�nge einer Bildzeile in Byte wieder.<br>
Falls das Farbformat unbekannt ist, wird -1 zur�ckgegeben.
*/
static int CalcPitch(BS_GraphicEngine::COLOR_FORMATS ColorFormat, int Width)
{
switch (ColorFormat)
{
case BS_GraphicEngine::CF_RGB16:
case BS_GraphicEngine::CF_RGB15:
return Width * 2;
case BS_GraphicEngine::CF_RGB16_INTERLEAVED:
case BS_GraphicEngine::CF_RGB15_INTERLEAVED:
return (Width + 3) / 4 * 12;
case BS_GraphicEngine::CF_ARGB32:
case BS_GraphicEngine::CF_ABGR32:
return Width * 4;
default:
BS_ASSERT(false);
}
return -1;
}
//@}
// Persistenz Methoden
// -------------------
virtual bool Persist(BS_OutputPersistenceBlock & Writer);
virtual bool Unpersist(BS_InputPersistenceBlock & Reader);
static void ARGBColorToLuaColor(lua_State * L, unsigned int Color);
static unsigned int LuaColorToARGBColor(lua_State * L, int StackIndex);
protected:
// Konstruktor
// -----------
BS_GraphicEngine(BS_Kernel* pKernel);
// Display Variablen
// -----------------
int m_Width;
int m_Height;
BS_Rect m_ScreenRect;
int m_BitDepth;
bool m_Windowed;
// Debugging-Variablen
// -------------------
BS_Framecounter m_FPSCounter;
unsigned int m_RepaintedPixels;
/**
@brief Berechnet die Zeit die seit dem letzten Framebeginn vergangen ist.
*/
void UpdateLastFrameDuration();
private:
bool RegisterScriptBindings();
// LastFrameDuration-Variablen
// ---------------------------
uint64_t m_LastTimeStamp;
unsigned int m_LastFrameDuration;
bool m_TimerActive;
std::vector<unsigned int> m_FrameTimeSamples;
unsigned int m_FrameTimeSampleSlot;
};
#endif
|