Nugget
gpu.hh
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2022 PCSX-Redux authors
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 
27 #pragma once
28 
29 #include <EASTL/array.h>
30 #include <EASTL/atomic.h>
31 #include <EASTL/functional.h>
32 #include <EASTL/utility.h>
33 #include <stdint.h>
34 
35 #include "common/hardware/hwregs.h"
36 #include "psyqo/primitives.hh"
37 
38 namespace psyqo {
39 
40 namespace DMA {
41 
42 enum DmaCallback {
43  FROM_ISR,
44  FROM_MAIN_LOOP,
45 };
46 
47 }
48 
57 class GPU {
58  public:
59  struct Configuration;
60  enum class Resolution { W256, W320, W368, W512, W640 };
61  enum class VideoMode { AUTO, NTSC, PAL };
62  enum class ColorMode { C15BITS, C24BITS };
63  enum class Interlace { PROGRESSIVE, INTERLACED };
64  void initialize(const Configuration &config);
65 
66  static constexpr uint32_t US_PER_HBLANK = 64;
67 
74  unsigned getRefreshRate() const { return m_refreshRate; }
75 
84  uint32_t getFrameCount() const { return m_frameCount; }
85 
93  void clear(Color bg = {{0, 0, 0}});
94 
105  void getClear(Prim::FastFill &ff, Color bg = {{0, 0, 0}}) const;
106 
118  void getNextClear(Prim::FastFill &ff, Color bg = {{0, 0, 0}}) const;
119 
131  void uploadToVRAM(const uint16_t *data, Rect region);
132 
156  void uploadToVRAM(const uint16_t *data, Rect region, eastl::function<void()> &&callback,
157  DMA::DmaCallback dmaCallback = DMA::FROM_MAIN_LOOP);
158 
165  template <typename Fragment>
166  void sendFragment(const Fragment &fragment) {
167  sendFragment(&fragment.head + 1, fragment.getActualFragmentSize());
168  }
169 
179  template <typename Fragment>
180  void sendFragment(const Fragment &fragment, eastl::function<void()> &&callback,
181  DMA::DmaCallback dmaCallback = DMA::FROM_MAIN_LOOP) {
182  sendFragment(&fragment.head + 1, fragment.getActualFragmentSize(), eastl::move(callback), dmaCallback);
183  }
184 
188  void disableScissor();
189 
196  void enableScissor();
197 
205  void getScissor(Prim::Scissor &scissor);
206 
215  void getNextScissor(Prim::Scissor &scissor);
216 
220  static void waitReady();
221 
225  static void sendRaw(uint32_t data) { GPU_DATA = data; }
226  template <typename Primitive>
227 
234  static void sendPrimitive(const Primitive &primitive) {
235  static_assert((sizeof(Primitive) % 4) == 0, "Primitive's size must be a multiple of 4");
236  waitReady();
237  const uint32_t *ptr = reinterpret_cast<const uint32_t *>(&primitive);
238  size_t size = sizeof(Primitive) / sizeof(uint32_t);
239  for (int i = 0; i < size; i++) {
240  sendRaw(*ptr++);
241  }
242  }
243 
257  template <typename Fragment>
258  void chain(Fragment &fragment) {
259  chain(&fragment.head, fragment.getActualFragmentSize());
260  }
261 
267  void sendChain();
268 
276  void sendChain(eastl::function<void()> &&callback, DMA::DmaCallback dmaCallback = DMA::FROM_MAIN_LOOP);
277 
283  bool isChainIdle() const;
284 
290  bool isChainTransferring() const;
291 
297  bool isChainTransferred() const;
298 
316  uint32_t now() const { return m_currentTime; }
317 
335  uintptr_t armTimer(uint32_t deadline, eastl::function<void(uint32_t)> &&callback);
336 
348  unsigned armPeriodicTimer(uint32_t period, eastl::function<void(uint32_t)> &&callback);
349 
364  void changeTimerPeriod(uintptr_t id, uint32_t period, bool reset = false);
365 
375  void pauseTimer(uintptr_t id);
376 
386  void resumeTimer(uintptr_t id);
387 
395  void cancelTimer(uintptr_t id);
396 
405  void pumpCallbacks();
406 
407  private:
408  void sendFragment(const uint32_t *data, size_t count);
409  void sendFragment(const uint32_t *data, size_t count, eastl::function<void()> &&callback,
410  DMA::DmaCallback dmaCallback);
411  void chain(uint32_t *head, size_t count);
412 
413  eastl::function<void(void)> m_dmaCallback = nullptr;
414  unsigned m_refreshRate = 0;
415  bool m_fromISR = false;
416  bool m_flushCacheAfterDMA = false;
417  int m_width = 0;
418  int m_height = 0;
419  uint32_t m_currentTime = 0;
420  uint32_t m_frameCount = 0;
421  uint32_t m_previousFrameCount = 0;
422  int m_parity = 0;
423  uint32_t *m_chainHead = nullptr;
424  uint32_t *m_chainTail = nullptr;
425  size_t m_chainTailCount = 0;
426  enum { CHAIN_IDLE, CHAIN_TRANSFERRING, CHAIN_TRANSFERRED } m_chainStatus;
427 
428  uint16_t m_lastHSyncCounter = 0;
429  bool m_interlaced = false;
430  void flip();
431  friend class Application;
432 };
433 
434 } // namespace psyqo
435 
436 #include "psyqo/internal/gpu/configuration.hh"
Definition: function.h:30
The singleton GPU class.
Definition: gpu.hh:57
void sendFragment(const Fragment &fragment, eastl::function< void()> &&callback, DMA::DmaCallback dmaCallback=DMA::FROM_MAIN_LOOP)
Sends a fragment to the GPU as a non-blocking call.
Definition: gpu.hh:180
bool isChainIdle() const
Gets the status of the background DMA transfer operation when initiated by a frame flip.
Definition: gpu.cpp:389
uint32_t getFrameCount() const
Returns the number of frames rendered by the GPU so far.
Definition: gpu.hh:84
void chain(Fragment &fragment)
Chains a fragment to the next DMA chain transfer.
Definition: gpu.hh:258
uintptr_t armTimer(uint32_t deadline, eastl::function< void(uint32_t)> &&callback)
Creates a single-use timer.
Definition: gpu.cpp:404
void disableScissor()
Immediately disables the scissoring of the VRAM.
Definition: gpu.cpp:181
void getClear(Prim::FastFill &ff, Color bg={{0, 0, 0}}) const
Sets a FastFill primitive to clear the current drawing buffer.
Definition: gpu.cpp:220
static void sendPrimitive(const Primitive &primitive)
Sends a primitive to the GPU. This is a blocking call.
Definition: gpu.hh:234
unsigned armPeriodicTimer(uint32_t period, eastl::function< void(uint32_t)> &&callback)
Creates a periodic timer.
Definition: gpu.cpp:409
void enableScissor()
Enables the scissoring of the VRAM.
Definition: gpu.cpp:186
static void waitReady()
Waits until the GPU is ready to send a command.
Definition: gpu.cpp:41
void getNextScissor(Prim::Scissor &scissor)
Gets the next scissoring region.
Definition: gpu.cpp:203
uint32_t now() const
Gets the current timestamp in microseconds.
Definition: gpu.hh:316
unsigned getRefreshRate() const
Returns the refresh rate of the GPU.
Definition: gpu.hh:74
void sendChain()
Immediately sends the current DMA chain.
Definition: gpu.cpp:356
void changeTimerPeriod(uintptr_t id, uint32_t period, bool reset=false)
Changes the period of a periodic timer.
Definition: gpu.cpp:414
void pauseTimer(uintptr_t id)
Pauses a timer.
Definition: gpu.cpp:430
void pumpCallbacks()
Runs one round of event processing.
Definition: gpu.cpp:458
void cancelTimer(uintptr_t id)
Cancels a timer.
Definition: gpu.cpp:450
bool isChainTransferred() const
Gets the status of the background DMA transfer operation when initiated by a frame flip.
Definition: gpu.cpp:399
void uploadToVRAM(const uint16_t *data, Rect region)
Uploads a buffer to the VRAM as a blocking call.
Definition: gpu.cpp:236
void getNextClear(Prim::FastFill &ff, Color bg={{0, 0, 0}}) const
Sets a FastFill primitive to clear the next drawing buffer.
Definition: gpu.cpp:228
static void sendRaw(uint32_t data)
Sends a raw 32 bits value to the GP0 register of the GPU.
Definition: gpu.hh:225
void sendFragment(const Fragment &fragment)
Immediately sends a fragment to the GPU. This is a blocking operation. See the fragments....
Definition: gpu.hh:166
void resumeTimer(uintptr_t id)
Resumes a paused timer.
Definition: gpu.cpp:440
bool isChainTransferring() const
Gets the status of the background DMA transfer operation when initiated by a frame flip.
Definition: gpu.cpp:394
void clear(Color bg={{0, 0, 0}})
Immediately clears the drawing buffer.
Definition: gpu.cpp:214
void getScissor(Prim::Scissor &scissor)
Gets the current scissoring region.
Definition: gpu.cpp:192
OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)
Definition: copy_help.h:170
Definition: configuration.hh:29
A compounded Scissor primitive.
Definition: control.hh:104
Definition: gpu.h:114
The Color struct.
Definition: common.hh:91