Etterna 0.74.4
Loading...
Searching...
No Matches
RageDisplay.h
1/* RageDisplay - Renderer base class. */
2
3#ifndef RAGEDISPLAY_H
4#define RAGEDISPLAY_H
5
6#include "Etterna/Actor/Base/ModelTypes.h"
7#include "RageUtil/Misc/RageTypes.h"
8
9#include <chrono>
10#include <set>
11#include <utility>
12
13class DisplaySpec;
14using DisplaySpecs = std::set<DisplaySpec>;
15
16const int REFRESH_DEFAULT = 0;
17struct RageSurface;
18enum TextureUnit
19{
20 TextureUnit_1,
21 TextureUnit_2,
22 TextureUnit_3,
23 TextureUnit_4,
24 TextureUnit_5,
25 TextureUnit_6,
26 TextureUnit_7,
27 TextureUnit_8,
28 NUM_TextureUnit
29};
30
31// RageCompiledGeometry holds vertex data in a format that is most efficient
32// for the graphics API.
34{
35 public:
36 virtual ~RageCompiledGeometry();
37
38 void Set(const std::vector<msMesh>& vMeshes, bool bNeedsNormals);
39
40 virtual void Allocate(const std::vector<msMesh>& vMeshes) = 0; // allocate space
41 virtual void Change(const std::vector<msMesh>& vMeshes) = 0; // new data must be
42 // the same size as
43 // was passed to
44 // Set()
45 virtual void Draw(int iMeshIndex) const = 0;
46
47 protected:
48 [[nodiscard]] auto GetTotalVertices() const -> size_t
49 {
50 if (m_vMeshInfo.empty()) {
51 return 0;
52 }
53 return m_vMeshInfo.back().iVertexStart +
54 m_vMeshInfo.back().iVertexCount;
55 }
56 [[nodiscard]] auto GetTotalTriangles() const -> size_t
57 {
58 if (m_vMeshInfo.empty()) {
59 return 0;
60 }
61 return m_vMeshInfo.back().iTriangleStart +
62 m_vMeshInfo.back().iTriangleCount;
63 }
64
65 struct MeshInfo
66 {
67 int iVertexStart;
68 int iVertexCount;
69 int iTriangleStart;
70 int iTriangleCount;
71 bool m_bNeedsTextureMatrixScale;
72 };
73 std::vector<MeshInfo> m_vMeshInfo;
74 bool m_bNeedsNormals{};
75 bool m_bAnyNeedsTextureMatrixScale{};
76};
77
78enum RagePixelFormat
79{
80 RagePixelFormat_RGBA8,
81 RagePixelFormat_BGRA8,
82 RagePixelFormat_RGBA4,
83 RagePixelFormat_RGB5A1,
84 RagePixelFormat_RGB5,
85 RagePixelFormat_RGB8,
86 RagePixelFormat_PAL,
87 /* The above formats differ between OpenGL and D3D. These are provided as
88 * alternatives for OpenGL that match some format in D3D. Don't use them
89 * directly; they'll be matched automatically by FindPixelFormat. */
90 RagePixelFormat_BGR8,
91 RagePixelFormat_A1BGR5,
92 RagePixelFormat_X1RGB5,
93 NUM_RagePixelFormat,
94 RagePixelFormat_Invalid
95};
96auto
97RagePixelFormatToString(RagePixelFormat i) -> const std::string&;
98
101{
102 public:
103 // Initialize with a constructor so to guarantee all paramters
104 // are filled (in case new params are added).
105 VideoModeParams(bool windowed_,
106 std::string sDisplayId_,
107 int width_,
108 int height_,
109 int bpp_,
110 int rate_,
111 bool vsync_,
112 bool interlaced_,
113 bool bSmoothLines_,
114 bool bTrilinearFiltering_,
115 bool bAnisotropicFiltering_,
116 bool bWindowIsFullscreenBorderless_,
117 std::string sWindowTitle_,
118 std::string sIconFile_,
119 bool PAL_,
120 float fDisplayAspectRatio_)
121 : windowed(windowed_)
122 , sDisplayId(std::move(sDisplayId_))
123 , width(width_)
124 , height(height_)
125 , bpp(bpp_)
126 , rate(rate_)
127 , vsync(vsync_)
128 , interlaced(interlaced_)
129 , bSmoothLines(bSmoothLines_)
130 , bTrilinearFiltering(bTrilinearFiltering_)
131 , bAnisotropicFiltering(bAnisotropicFiltering_)
132 , bWindowIsFullscreenBorderless(bWindowIsFullscreenBorderless_)
133 , sWindowTitle(std::move(sWindowTitle_))
134 , sIconFile(std::move(sIconFile_))
135 , PAL(PAL_)
136 , fDisplayAspectRatio(fDisplayAspectRatio_)
137 {
138 }
139
140 VideoModeParams(const VideoModeParams& other)
141 : windowed(other.windowed)
142 , sDisplayId(other.sDisplayId)
143 , width(other.width)
144 , height(other.height)
145 , bpp(other.bpp)
146 , rate(other.rate)
147 , vsync(other.vsync)
148 , interlaced(other.interlaced)
149 , bSmoothLines(other.bSmoothLines)
150 , bTrilinearFiltering(other.bTrilinearFiltering)
151 , bAnisotropicFiltering(other.bAnisotropicFiltering)
152 , bWindowIsFullscreenBorderless(other.bWindowIsFullscreenBorderless)
153 , sWindowTitle(other.sWindowTitle)
154 , sIconFile(other.sIconFile)
155 , PAL(other.PAL)
156 , fDisplayAspectRatio(other.fDisplayAspectRatio)
157 {
158 }
159
161 : windowed(other.windowed)
162 , sDisplayId(std::move(other.sDisplayId))
163 , width(other.width)
164 , height(other.height)
165 , bpp(other.bpp)
166 , rate(other.rate)
167 , vsync(other.vsync)
168 , interlaced(other.interlaced)
169 , bSmoothLines(other.bSmoothLines)
170 , bTrilinearFiltering(other.bTrilinearFiltering)
171 , bAnisotropicFiltering(other.bAnisotropicFiltering)
172 , bWindowIsFullscreenBorderless(other.bWindowIsFullscreenBorderless)
173 , sWindowTitle(std::move(other.sWindowTitle))
174 , sIconFile(std::move(other.sIconFile))
175 , PAL(other.PAL)
176 , fDisplayAspectRatio(other.fDisplayAspectRatio)
177 {
178 }
179 VideoModeParams() = default;
180 VideoModeParams& operator=(const VideoModeParams&) = default;
181 virtual ~VideoModeParams() {}
182
183 bool windowed{ false };
184 std::string sDisplayId;
185 int width{ 0 };
186 int height{ 0 };
187 int bpp{ 0 };
188 int rate{ 0 };
189 bool vsync{ false };
190 bool interlaced{ false };
191 bool bSmoothLines{ false };
192 bool bTrilinearFiltering{ false };
193 bool bAnisotropicFiltering{ false };
194 bool bWindowIsFullscreenBorderless{ false };
195 std::string sWindowTitle;
196 std::string sIconFile;
197 bool PAL{ false };
198 float fDisplayAspectRatio{ 0.0F };
199};
200
207{
208 public:
210 : VideoModeParams(params)
211 , windowWidth(params.width)
212 , windowHeight(params.height)
213 {
214 }
216 : VideoModeParams(params)
217 , windowWidth(params.width)
218 , windowHeight(params.height)
219 {
220 }
222 int windowWidth,
223 int windowHeight,
224 bool renderOffscreen)
225 : VideoModeParams(params)
226 , windowWidth(windowWidth)
227 , windowHeight(windowHeight)
228 , renderOffscreen(renderOffscreen)
229 {
230 }
231
232 ActualVideoModeParams() = default;
233 ActualVideoModeParams& operator=(const ActualVideoModeParams&) = default;
234
235 // If bWindowIsFullscreenBorderless is true,
236 // then these properties will differ from width/height (which describe the
237 // render size)
238 int windowWidth{ 0 };
239 int windowHeight{ 0 };
240 bool renderOffscreen{ false };
241};
242
244{
245 RenderTargetParam() = default;
246
247 // The dimensions of the actual render target, analogous to a window size:
248 int iWidth{ 0 }, iHeight{ 0 };
249
250 bool bWithDepthBuffer{ false };
251 bool bWithAlpha{ false };
252 bool bFloat{ false };
253};
254
256{
257 virtual ~RageTextureLock() = default;
258
259 /* Given a surface with a format and no pixel data, lock the texture into
260 * the surface. The data is write-only. */
261 virtual void Lock(unsigned iTexHandle, RageSurface* pSurface) = 0;
262
263 /* Unlock and update the texture. If bChanged is false, the texture update
264 * may be omitted. */
265 virtual void Unlock(RageSurface* pSurface, bool bChanged = true) = 0;
266};
267
269{
270 friend class RageTexture;
271
272 public:
274 {
275 int bpp;
276 unsigned int masks[4];
277 };
278
279 [[nodiscard]] virtual auto GetPixelFormatDesc(RagePixelFormat pf) const
280 -> const RagePixelFormatDesc* = 0;
281
282 RageDisplay();
283 virtual ~RageDisplay();
284
285 virtual auto Init(VideoModeParams&& p,
286 bool bAllowUnacceleratedRenderer) -> std::string = 0;
287
288 [[nodiscard]] virtual auto GetApiDescription() const -> std::string = 0;
289 virtual void GetDisplaySpecs(DisplaySpecs& out) const = 0;
290
291 void SetPresentTime(std::chrono::nanoseconds presentTime);
292
293 // Don't override this. Override TryVideoMode() instead.
294 // This will set the video mode to be as close as possible to params.
295 // Return true if device was re-created and we need to reload textures.
296 auto SetVideoMode(VideoModeParams&& p, bool& bNeedReloadTextures)
297 -> std::string;
298
299 // Call this when the resolution has been changed externally:
300 virtual void ResolutionChanged();
301 auto IsD3D() -> bool;
302
303 virtual auto BeginFrame() -> bool;
304 virtual void EndFrame();
305 [[nodiscard]] virtual auto GetActualVideoModeParams() const
306 -> const ActualVideoModeParams* = 0;
307 auto IsWindowed() -> bool { return (*GetActualVideoModeParams()).windowed; }
308
309 auto GetFrameTimingAdjustment(std::chrono::steady_clock::time_point now)
310 -> float;
311
312 virtual void SetBlendMode(BlendMode mode) = 0;
313
314 virtual auto SupportsTextureFormat(RagePixelFormat pixfmt,
315 bool realtime = false) -> bool = 0;
316 virtual auto SupportsThreadedRendering() -> bool { return false; }
317 virtual auto SupportsPerVertexMatrixScale() -> bool = 0;
318
319 // If threaded rendering is supported, these will be called from the
320 // rendering thread before and after rendering.
321 virtual void BeginConcurrentRenderingMainThread() {}
322 virtual void EndConcurrentRenderingMainThread() {}
323 virtual void BeginConcurrentRendering();
324 virtual void EndConcurrentRendering() {}
325
326 /* return 0 if failed or internal texture resource handle
327 * (unsigned in OpenGL, texture pointer in D3D) */
328 virtual auto CreateTexture(
329 RagePixelFormat pixfmt, // format of img and of texture in video mem
330 RageSurface* img, // must be in pixfmt
331 bool bGenerateMipMaps) -> intptr_t = 0;
332 virtual void UpdateTexture(intptr_t iTexHandle,
333 RageSurface* img,
334 int xoffset,
335 int yoffset,
336 int width,
337 int height) = 0;
338 virtual void DeleteTexture(intptr_t iTexHandle) = 0;
339 /* Return an object to lock pixels for streaming. If not supported, returns
340 * NULL. Delete the object normally. */
341 virtual auto CreateTextureLock() -> RageTextureLock* { return nullptr; }
342 virtual void ClearAllTextures() = 0;
343 virtual auto GetNumTextureUnits() -> int = 0;
344 virtual void SetTexture(TextureUnit, intptr_t /* iTexture */) = 0;
345 virtual void SetTextureMode(TextureUnit, TextureMode) = 0;
346 virtual void SetTextureWrapping(TextureUnit, bool) = 0;
347 [[nodiscard]] virtual auto GetMaxTextureSize() const -> int = 0;
348 virtual void SetTextureFiltering(TextureUnit, bool) = 0;
349 virtual void SetEffectMode(EffectMode /*unused*/) {}
350 virtual auto IsEffectModeSupported(EffectMode effect) -> bool
351 {
352 return effect == EffectMode_Normal;
353 }
354
355 [[nodiscard]] virtual auto SupportsRenderToTexture() const -> bool
356 {
357 return false;
358 }
359 [[nodiscard]] virtual auto SupportsFullscreenBorderlessWindow() const
360 -> bool
361 {
362 return false;
363 }
364
365 /* Create a render target, returning a texture handle. In addition to normal
366 * texture functions, this can be passed to SetRenderTarget. Delete with
367 * DeleteTexture. (UpdateTexture is not permitted.) Returns 0 if render-to-
368 * texture is unsupported.
369 */
370 virtual auto CreateRenderTarget(const RenderTargetParam& /*unused*/,
371 int& /* iTextureWidthOut */,
372 int &
373 /* iTextureHeightOut */) -> intptr_t
374 {
375 return 0;
376 }
377
378 virtual auto GetRenderTarget() -> intptr_t { return 0; }
379
380 /* Set the render target, or 0 to resume rendering to the framebuffer. An
381 * active render target may not be used as a texture. If bPreserveTexture is
382 * true, the contents of the texture will be preserved from the previous
383 * call; otherwise, cleared. If bPreserveTexture is true the first time a
384 * render target is used, behave as if bPreserveTexture was false.
385 */
386 virtual void SetRenderTarget(intptr_t /* iHandle */,
387 bool /* bPreserveTexture */ = true)
388 {
389 }
390
391 [[nodiscard]] virtual auto IsZTestEnabled() const -> bool = 0;
392 [[nodiscard]] virtual auto IsZWriteEnabled() const -> bool = 0;
393 virtual void SetZWrite(bool) = 0;
394 virtual void SetZTestMode(ZTestMode) = 0;
395 virtual void SetZBias(float) = 0;
396 virtual void ClearZBuffer() = 0;
397
398 virtual void SetCullMode(CullMode mode) = 0;
399
400 virtual void SetAlphaTest(bool b) = 0;
401
402 virtual void SetMaterial(const RageColor& emissive,
403 const RageColor& ambient,
404 const RageColor& diffuse,
405 const RageColor& specular,
406 float shininess) = 0;
407
408 virtual void SetLighting(bool b) = 0;
409 virtual void SetLightOff(int index) = 0;
410 virtual void SetLightDirectional(int index,
411 const RageColor& ambient,
412 const RageColor& diffuse,
413 const RageColor& specular,
414 const RageVector3& dir) = 0;
415
416 virtual void SetSphereEnvironmentMapping(TextureUnit tu, bool b) = 0;
417 virtual void SetCelShaded(int stage) = 0;
418
419 virtual auto CreateCompiledGeometry() -> RageCompiledGeometry* = 0;
420 virtual void DeleteCompiledGeometry(RageCompiledGeometry* p) = 0;
421
422 void DrawQuads(const RageSpriteVertex v[], int iNumVerts);
423 void DrawQuadStrip(const RageSpriteVertex v[], int iNumVerts);
424 void DrawFan(const RageSpriteVertex v[], int iNumVerts);
425 void DrawStrip(const RageSpriteVertex v[], int iNumVerts);
426 void DrawTriangles(const RageSpriteVertex v[], int iNumVerts);
427 void DrawCompiledGeometry(const RageCompiledGeometry* p,
428 int iMeshIndex,
429 const std::vector<msMesh>& vMeshes);
430 void DrawLineStrip(const RageSpriteVertex v[],
431 int iNumVerts,
432 float LineWidth);
433 void DrawSymmetricQuadStrip(const RageSpriteVertex v[], int iNumVerts);
434 void DrawCircle(const RageSpriteVertex& v, float radius);
435
436 void DrawQuad(const RageSpriteVertex v[])
437 {
438 DrawQuads(v, 4);
439 } /* alias. upper-left, upper-right, lower-left, lower-right */
440
441 // hacks for cell-shaded models
442 virtual void SetPolygonMode(PolygonMode /*unused*/) {}
443 virtual void SetLineWidth(float /*unused*/) {}
444
445 enum GraphicsFileFormat
446 {
447 SAVE_LOSSLESS, // bmp
448 SAVE_LOSSLESS_SENSIBLE, // png
449 SAVE_LOSSY_LOW_QUAL, // jpg
450 SAVE_LOSSY_HIGH_QUAL // jpg
451 };
452 auto SaveScreenshot(const std::string& sPath, GraphicsFileFormat format)
453 -> bool;
454
455 [[nodiscard]] virtual auto GetTextureDiagnostics(unsigned /* id */) const
456 -> std::string
457 {
458 return std::string();
459 }
460 virtual auto CreateScreenshot()
461 -> RageSurface* = 0; // allocates a surface. Caller must delete it.
462 virtual auto GetTexture(intptr_t /* iTexture */) -> RageSurface*
463 {
464 return nullptr;
465 } // allocates a surface. Caller must delete it.
466
467 protected:
468 virtual void DrawQuadsInternal(const RageSpriteVertex v[],
469 int iNumVerts) = 0;
470 virtual void DrawQuadStripInternal(const RageSpriteVertex v[],
471 int iNumVerts) = 0;
472 virtual void DrawFanInternal(const RageSpriteVertex v[], int iNumVerts) = 0;
473 virtual void DrawStripInternal(const RageSpriteVertex v[],
474 int iNumVerts) = 0;
475 virtual void DrawTrianglesInternal(const RageSpriteVertex v[],
476 int iNumVerts) = 0;
477 virtual void DrawCompiledGeometryInternal(const RageCompiledGeometry* p,
478 int iMeshIndex) = 0;
479 virtual void DrawLineStripInternal(const RageSpriteVertex v[],
480 int iNumVerts,
481 float LineWidth);
482 virtual void DrawSymmetricQuadStripInternal(const RageSpriteVertex v[],
483 int iNumVerts) = 0;
484 virtual void DrawCircleInternal(const RageSpriteVertex& v, float radius);
485
486 virtual auto IsD3DInternal() -> bool;
487
488 // return std::string() if mode change was successful, an error message
489 // otherwise. bNewDeviceOut is set true if a new device was created and
490 // textures need to be reloaded.
491 virtual auto TryVideoMode(const VideoModeParams& p, bool& bNewDeviceOut)
492 -> std::string = 0;
493
494 void DrawPolyLine(const RageSpriteVertex& p1,
495 const RageSpriteVertex& p2,
496 float LineWidth);
497 void DrawPolyLines(const RageSpriteVertex v[],
498 int iNumVerts,
499 float LineWidth);
500
501 // Stuff in RageDisplay.cpp
502 void SetDefaultRenderStates();
503
504 public:
505 // Statistics
506 [[nodiscard]] auto IsPredictiveFrameLimit() const -> bool;
507 [[nodiscard]] auto GetFPS() const -> int;
508 [[nodiscard]] auto GetVPF() const -> int;
509 [[nodiscard]] auto GetCumFPS() const -> int; // average FPS since last reset
510 virtual void ResetStats();
511 virtual void ProcessStatsOnFlip();
512 [[nodiscard]] virtual auto GetStats() const -> std::string;
513 void StatsAddVerts(int iNumVertsRendered);
514
515 // World matrix stack functions.
516 void PushMatrix();
517 void PopMatrix();
518 void Translate(float x, float y, float z);
519 void TranslateWorld(float x, float y, float z);
520 void Scale(float x, float y, float z);
521 void RotateX(float deg);
522 void RotateY(float deg);
523 void RotateZ(float deg);
524 void SkewX(float fAmount);
525 void SkewY(float fAmount);
526 void MultMatrix(const RageMatrix& f)
527 {
528 this->PostMultMatrix(f);
529 } /* alias */
530 void PostMultMatrix(const RageMatrix& f);
531 void PreMultMatrix(const RageMatrix& f);
532 void LoadIdentity();
533
534 // Texture matrix functions
535 void TexturePushMatrix();
536 void TexturePopMatrix();
537 void TextureTranslate(float x, float y);
538 void TextureTranslate(const RageVector2& v)
539 {
540 this->TextureTranslate(v.x, v.y);
541 }
542
543 // Projection and View matrix stack functions.
544 void CameraPushMatrix();
545 void CameraPopMatrix();
546 void LoadMenuPerspective(float fFOVDegrees,
547 float fWidth,
548 float fHeight,
549 float fVanishPointX,
550 float fVanishPointY);
551 void LoadLookAt(float fov,
552 const RageVector3& Eye,
553 const RageVector3& At,
554 const RageVector3& Up);
555
556 // Centering matrix
557 void CenteringPushMatrix();
558 void CenteringPopMatrix();
559 void ChangeCentering(int trans_x,
560 int trans_y,
561 int add_width,
562 int add_height);
563
564 auto CreateSurfaceFromPixfmt(RagePixelFormat pixfmt,
565 void* pixels,
566 int width,
567 int height,
568 int pitch) -> RageSurface*;
569 auto FindPixelFormat(int bpp,
570 unsigned Rmask,
571 unsigned Gmask,
572 unsigned Bmask,
573 unsigned Amask,
574 bool realtime = false) -> RagePixelFormat;
575
576 // Lua
577 void PushSelf(lua_State* L);
578
579 protected:
580 auto GetPerspectiveMatrix(float fovy, float aspect, float zNear, float zFar)
581 -> RageMatrix;
582
583 // Different for D3D and OpenGL. Not sure why they're not compatible. -Chris
584 virtual auto GetOrthoMatrix(float l,
585 float r,
586 float b,
587 float t,
588 float zn,
589 float zf) -> RageMatrix;
590 virtual auto GetFrustumMatrix(float l,
591 float r,
592 float b,
593 float t,
594 float zn,
595 float zf) -> RageMatrix;
596
597 // Matrix that adjusts position and scale of image on the screen
598 auto GetCenteringMatrix(float fTranslateX,
599 float fTranslateY,
600 float fAddWidth,
601 float fAddHeight) -> RageMatrix;
602 void UpdateCentering();
603
604 // Called by the RageDisplay derivitives
605 [[nodiscard]] auto GetCentering() const -> const RageMatrix*;
606 [[nodiscard]] auto GetProjectionTop() const -> const RageMatrix*;
607 [[nodiscard]] auto GetViewTop() const -> const RageMatrix*;
608 [[nodiscard]] auto GetWorldTop() const -> const RageMatrix*;
609 [[nodiscard]] auto GetTextureTop() const -> const RageMatrix*;
610
611 void FrameLimitBeforeVsync();
612 void FrameLimitAfterVsync(int iFPS);
613};
614
615extern RageDisplay*
616 DISPLAY; // global and accessible from anywhere in our program
617
618#endif
The actual VideoModeParams determined by the LowLevelWindow implementation. Contains all the attribut...
Definition RageDisplay.h:207
The dimensions of the program.
Definition DisplaySpec.h:48
Definition RageDisplay.h:34
Definition RageDisplay.h:269
Definition RageTexture.h:14
The parameters used for the present Video Mode.
Definition RageDisplay.h:101
Definition RageTypes.h:332
Definition RageDisplay.h:66
Definition RageDisplay.h:274
Definition RageTypes.h:599
Definition RageTypes.h:557
Definition RageSurface.h:90
Definition RageDisplay.h:256
Definition RageTypes.h:101
Definition RageTypes.h:172
Definition RageDisplay.h:244
Definition ModelTypes.h:15