1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "BsGLPrerequisites.h" |
6 | #include "RenderAPI/BsHardwareBuffer.h" |
7 | #include "Image/BsPixelUtil.h" |
8 | |
9 | namespace bs { namespace ct |
10 | { |
11 | /** @addtogroup GL |
12 | * @{ |
13 | */ |
14 | |
15 | class GLTextureBuffer; |
16 | |
17 | /** |
18 | * Represents a hardware buffer that stores a single pixel surface. This may be a 1D, 2D or 3D surface, but unlike a |
19 | * texture it consists only of a single surface (no mip maps, cube map faces or similar). |
20 | */ |
21 | class GLPixelBuffer |
22 | { |
23 | public: |
24 | /** |
25 | * Constructs a new pixel buffer with the provided settings. |
26 | * |
27 | * @param[in] width Width of the pixel buffer in pixels. |
28 | * @param[in] height Height of the pixel buffer in pixels. |
29 | * @param[in] depth Depth of the pixel buffer in pixels (number of 2D slices). |
30 | * @param[in] format Format of each pixel in the buffer. |
31 | * @param[in] usage Usage signaling the render system how we plan on using the buffer. |
32 | */ |
33 | GLPixelBuffer(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format, GpuBufferUsage usage); |
34 | virtual ~GLPixelBuffer(); |
35 | |
36 | /** Returns width of the surface in pixels. */ |
37 | UINT32 getWidth() const { return mWidth; } |
38 | |
39 | /** Returns height of the surface in pixels. */ |
40 | UINT32 getHeight() const { return mHeight; } |
41 | |
42 | /** Returns depth of the surface in pixels. */ |
43 | UINT32 getDepth() const { return mDepth; } |
44 | |
45 | /** Returns format of the pixels in the surface. */ |
46 | PixelFormat getFormat() const { return mFormat; } |
47 | |
48 | /** |
49 | * Locks a certain region of the pixel buffer for reading and returns a pointer to the locked region. |
50 | * |
51 | * @param[in] lockBox Region of the surface to lock. |
52 | * @param[in] options Lock options that hint the hardware on what you intend to do with the locked data. |
53 | * |
54 | * @note Returned object is only valid while the lock is active. |
55 | */ |
56 | const PixelData& lock(const PixelVolume& lockBox, GpuLockOptions options); |
57 | |
58 | /** |
59 | * Locks a portion of the buffer and returns pointer to the locked area. You must call unlock() when done. |
60 | * |
61 | * @param[in] offset Offset in bytes from which to lock the buffer. |
62 | * @param[in] length Length of the area you want to lock, in bytes. |
63 | * @param[in] options Signifies what you want to do with the returned pointer. Caller must ensure not to do |
64 | * anything he hasn't requested (for example don't try to read from the buffer unless you |
65 | * requested it here). |
66 | */ |
67 | void* lock(UINT32 offset, UINT32 length, GpuLockOptions options); |
68 | |
69 | /** |
70 | * Locks the entire buffer and returns pointer to the locked area. You must call unlock() when done. |
71 | * |
72 | * @param[in] options Signifies what you want to do with the returned pointer. Caller must ensure not to do |
73 | * anything he hasn't requested (for example don't try to read from the buffer unless you |
74 | * requested it here). |
75 | */ |
76 | void* lock(GpuLockOptions options) |
77 | { |
78 | return lock(0, mSizeInBytes, options); |
79 | } |
80 | |
81 | /** Releases the lock on this buffer. */ |
82 | void unlock(); |
83 | |
84 | /** |
85 | * Upload some pixel data to the buffer. |
86 | * |
87 | * @param[in] data Data to upload. |
88 | * @param[in] dest Coordinates to which to upload the data. |
89 | */ |
90 | virtual void upload(const PixelData& data, const PixelVolume& dest); |
91 | |
92 | /** |
93 | * Reads data from the pixel buffer into the provided object. Caller must ensure the data object is of adequate |
94 | * size. |
95 | */ |
96 | virtual void download(const PixelData& data); |
97 | |
98 | /** |
99 | * Binds the buffers to a frame buffer object at the specified attachment point. |
100 | * |
101 | * @param[in] attachment Attachment point index in the range [0, BS_MAX_MULTIPLE_RENDER_TARGETS). |
102 | * @param[in] zoffset Depth slice to bind, in the case of a 3D texture. |
103 | * @param[in] allLayers Should all layers of the texture be bound, or just one (zoffset is ignored if true). |
104 | */ |
105 | virtual void bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers); |
106 | |
107 | /** |
108 | * Blits the contents of the provided buffer into this pixel buffer. Data is bilinearily interpolated in case buffer |
109 | * sizes don't match. |
110 | */ |
111 | virtual void blitFromTexture(GLTextureBuffer* src); |
112 | |
113 | /** |
114 | * Blits contents of a sub-region of the provided buffer into a sub-region of this pixel buffer. Data is bilinearily |
115 | * interpolated in case source and destination sizes don't match. |
116 | */ |
117 | virtual void blitFromTexture(GLTextureBuffer* src, const PixelVolume& srcBox, const PixelVolume& dstBox); |
118 | |
119 | protected: |
120 | /** Allocates an internal buffer on the CPU, the size of the hardware buffer. */ |
121 | void allocateBuffer(); |
122 | |
123 | /** Deallocates the internal CPU buffer. */ |
124 | void freeBuffer(); |
125 | |
126 | protected: |
127 | UINT32 mSizeInBytes; |
128 | GpuBufferUsage mUsage; |
129 | bool mIsLocked = false; |
130 | |
131 | UINT32 mWidth, mHeight, mDepth; |
132 | PixelFormat mFormat; |
133 | |
134 | PixelData mCurrentLock; |
135 | PixelVolume mLockedBox; |
136 | |
137 | PixelData mBuffer; |
138 | GpuLockOptions mCurrentLockOptions; |
139 | }; |
140 | |
141 | /** Pixel buffer specialization that represents a single surface in a texture. */ |
142 | class GLTextureBuffer : public GLPixelBuffer |
143 | { |
144 | public: |
145 | /** |
146 | * Constructs a new texture buffer from a specific surface in the provided texture. |
147 | * |
148 | * @param[in] target OpenGL type of the texture to retrieve the surface from. |
149 | * @param[in] id OpenGL handle to the texture to retrieve the surface from. |
150 | * @param[in] face Face index of the texture in the case of cube textures or texture arrays. |
151 | * @param[in] level Mip level of the texture. |
152 | * @param[in] format Format of each pixel in the buffer. |
153 | * @param[in] usage Usage signaling the render system how we plan on using the buffer. |
154 | * @param[in] hwGamma True if buffer colors are assumed to be in sRGB space. |
155 | * @param[in] multisampleCount Number of samples the parent texture was created with. |
156 | */ |
157 | GLTextureBuffer(GLenum target, GLuint id, GLint face, |
158 | GLint level, PixelFormat format, GpuBufferUsage usage, bool hwGamma, UINT32 multisampleCount); |
159 | ~GLTextureBuffer() = default; |
160 | |
161 | /** @copydoc GLPixelBuffer::bindToFramebuffer */ |
162 | void bindToFramebuffer(GLenum attachment, UINT32 zoffset, bool allLayers) override; |
163 | |
164 | /** @copydoc GLPixelBuffer::upload */ |
165 | void upload(const PixelData &data, const PixelVolume &dest) override; |
166 | |
167 | /** @copydoc GLPixelBuffer::download */ |
168 | void download(const PixelData &data) override; |
169 | |
170 | /** @copydoc GLPixelBuffer::blitFromTexture */ |
171 | void blitFromTexture(GLTextureBuffer *src) override; |
172 | |
173 | /** @copydoc GLPixelBuffer::blitFromTexture */ |
174 | void blitFromTexture(GLTextureBuffer *src, const PixelVolume &srcBox, const PixelVolume &dstBox) override; |
175 | |
176 | /** |
177 | * Populate texture buffer with the data in the currently attached frame buffer. |
178 | * |
179 | * @param[in] zoffset 3D slice of the texture to copy to. 0 if texture is not 3D. |
180 | */ |
181 | void copyFromFramebuffer(UINT32 zoffset); |
182 | |
183 | protected: |
184 | GLenum mTarget; |
185 | GLenum mFaceTarget = 0; |
186 | GLuint mTextureID; |
187 | GLint mFace; |
188 | GLint mLevel; |
189 | UINT32 mMultisampleCount; |
190 | bool mHwGamma; |
191 | }; |
192 | |
193 | /** @} */ |
194 | }} |