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
9namespace 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}}