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