finish gl backend

This commit is contained in:
halx99 2020-09-11 01:19:10 +08:00
parent e53fa3560b
commit d2acbe176e
8 changed files with 83 additions and 105 deletions

View File

@ -485,7 +485,6 @@ void RenderTexture::newImage(std::function<void(Image*)> imageCallback, bool fli
auto image = new(std::nothrow) Image();
image->initWithRawData(pbd._data.getBytes(), pbd._data.getSize(), pbd._width, pbd._height, 8);
imageCallback(image);
image->release();
}
else imageCallback(nullptr);
};

View File

@ -71,81 +71,6 @@ int ccNextPOT(int x)
namespace utils
{
/**
* Capture screen implementation, don't use it directly.
*/
void onCaptureScreen(const std::function<void(bool, const std::string&)>& afterCaptured, const std::string& filename, const unsigned char* imageData, int width, int height)
{
if(!imageData)
{
afterCaptured(false, "");
return;
}
static bool startedCapture = false;
if (startedCapture)
{
CCLOG("Screen capture is already working");
if (afterCaptured)
{
afterCaptured(false, filename);
}
return;
}
else
{
startedCapture = true;
}
bool succeed = false;
std::string outputFile = "";
do
{
Image* image = new (std::nothrow) Image;
if (image)
{
image->initWithRawData(imageData, width * height * 4, width, height, 8);
if (FileUtils::getInstance()->isAbsolutePath(filename))
{
outputFile = filename;
}
else
{
CCASSERT(filename.find('/') == std::string::npos, "The existence of a relative path is not guaranteed!");
outputFile = FileUtils::getInstance()->getWritablePath() + filename;
}
// Save image in AsyncTaskPool::TaskType::TASK_IO thread, and call afterCaptured in mainThread
static bool succeedSaveToFile = false;
std::function<void(void*)> mainThread = [afterCaptured, outputFile](void* /*param*/)
{
if (afterCaptured)
{
afterCaptured(succeedSaveToFile, outputFile);
}
startedCapture = false;
};
AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_IO, std::move(mainThread), nullptr, [image, outputFile]()
{
succeedSaveToFile = image->saveToFile(outputFile);
delete image;
});
}
else
{
CCLOG("Malloc Image memory failed!");
if (afterCaptured)
{
afterCaptured(succeed, outputFile);
}
startedCapture = false;
}
} while (0);
}
/*
* Capture screen interface
*/
@ -164,7 +89,6 @@ void captureScreen(std::function<void(Image*)> imageCallback)
auto image = new(std::nothrow) Image();
image->initWithRawData(pbd._data.getBytes(), pbd._data.getSize(), pbd._width, pbd._height, 8);
imageCallback(image);
image->release();
}
else imageCallback(nullptr);
};

View File

@ -51,11 +51,14 @@ struct TextureDescriptor
SamplerDescriptor samplerDescriptor;
};
class UtilsGL;
/**
* A base texture
*/
class TextureBackend : public Ref
{
friend class UtilsGL;
public:
/**
* Update sampler
@ -98,7 +101,7 @@ public:
virtual int getCount() const { return 1; };
virtual uintptr_t getGPUHandler(int index = 0) const { return 0; }
virtual uintptr_t getHandler(int index = 0) const { return 0; }
int getWidth() const { return _width; }
int getHeight() const { return _height; }

View File

@ -628,32 +628,43 @@ void CommandBufferGL::setScissorRect(bool isEnabled, float x, float y, float wid
}
}
void CommandBufferGL::captureScreen(std::function<void(const unsigned char*, int, int)> callback)
void CommandBufferGL::capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback)
{
int bufferSize = _viewPort.w * _viewPort.h *4;
std::shared_ptr<GLubyte> buffer(new GLubyte[bufferSize], [](GLubyte* p){ CC_SAFE_DELETE_ARRAY(p); });
memset(buffer.get(), 0, bufferSize);
if (!buffer)
{
callback(nullptr, 0, 0);
return;
}
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, _viewPort.w, _viewPort.h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get());
PixelBufferDescriptor pbd;
if (!texture) { // screen capture
std::shared_ptr<GLubyte> flippedBuffer(new GLubyte[bufferSize], [](GLubyte* p) { CC_SAFE_DELETE_ARRAY(p); });
memset(flippedBuffer.get(), 0, bufferSize);
if (!flippedBuffer)
{
callback(nullptr, 0, 0);
return;
int bufferSize = _viewPort.w * _viewPort.h * 4;
std::unique_ptr<GLubyte[]> buffer(new GLubyte[bufferSize]);
memset(buffer.get(), 0, bufferSize);
if (!buffer)
{
callback(pbd);
return;
}
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, _viewPort.w, _viewPort.h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get());
GLubyte* flippedBuffer = (GLubyte*)malloc(bufferSize);
memset(flippedBuffer, 0, bufferSize);
if (!flippedBuffer)
{
callback(pbd);
return;
}
for (int row = 0; row < _viewPort.h; ++row)
{
memcpy(flippedBuffer + (_viewPort.h - row - 1) * _viewPort.w * 4, buffer.get() + row * _viewPort.w * 4, _viewPort.w * 4);
}
pbd._width = _viewPort.w;
pbd._height = _viewPort.h;
pbd._data.fastSet(flippedBuffer, bufferSize);
}
for (int row = 0; row < _viewPort.h; ++row)
{
memcpy(flippedBuffer.get() + (_viewPort.h - row - 1) * _viewPort.w * 4, buffer.get() + row * _viewPort.w * 4, _viewPort.w * 4);
else {
UtilsGL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), true, pbd);
}
callback(flippedBuffer.get(), _viewPort.w, _viewPort.h);
callback(pbd);
}
CC_BACKEND_END

View File

@ -167,7 +167,7 @@ public:
* Get a screen snapshot
* @param callback A callback to deal with screen snapshot image.
*/
virtual void captureScreen(std::function<void(const unsigned char*, int, int)> callback) override ;
virtual void capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback) override;
private:
struct Viewport

View File

@ -165,7 +165,7 @@ public:
* Get texture object.
* @return Texture object.
*/
inline GLuint getHandler(int index = 0) const { return _textureInfo.textures[index]; }
uintptr_t getHandler(int index = 0) const override { return _textureInfo.textures[index]; }
/**
* Set texture to pipeline
@ -175,8 +175,6 @@ public:
int getCount() const override { return _textureInfo.maxIdx + 1; }
uintptr_t getGPUHandler(int index) const override { return _textureInfo.getName(index); }
private:
void initWithZeros();
@ -222,7 +220,7 @@ public:
* Get texture object.
* @return Texture object.
*/
inline GLuint getHandler(int index = 0) const { return _textureInfo.textures[index]; }
uintptr_t getHandler(int index = 0) const override { return _textureInfo.textures[index]; }
/**
* Set texture to pipeline

View File

@ -25,6 +25,7 @@
#include "UtilsGL.h"
#include "ProgramGL.h"
#include "TextureGL.h"
#include "renderer/backend/Types.h"
#if !defined(GL_COMPRESSED_RGB8_ETC2)
@ -591,4 +592,46 @@ GLenum UtilsGL::toGLCullMode(CullMode mode)
return GL_FRONT;
}
void UtilsGL::readPixels(TextureBackend* texture, std::size_t x, std::size_t y, std::size_t width, std::size_t height, bool flipImage, PixelBufferDescriptor& outbuffer)
{
GLint defaultFBO = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
GLuint frameBuffer = 0;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
texture->getTextureType() == TextureType::TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP,
static_cast<GLuint>(texture->getHandler()),
0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
auto bytePerRow = width * texture->_bitsPerElement / 8;
uint8_t* image = (uint8_t*)malloc(bytePerRow * height);
glReadPixels(x,y,width, height,GL_RGBA,GL_UNSIGNED_BYTE, image);
outbuffer._width = width;
outbuffer._height = height;
if(flipImage)
{
uint8_t* flippedImage = (uint8_t*)malloc(bytePerRow * height);
for (int i = 0; i < height; ++i)
{
memcpy(&flippedImage[i * bytePerRow],
&image[(height - i - 1) * bytePerRow],
bytePerRow);
}
outbuffer._data.fastSet(flippedImage, bytePerRow * height);
CC_SAFE_FREE(image);
}
else
{
outbuffer._data.fastSet(image, bytePerRow * height);
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glDeleteFramebuffers(1, &frameBuffer);
}
CC_BACKEND_END

View File

@ -162,7 +162,7 @@ struct UtilsGL
* @param outbuffer, the output buffer for fill texels data
* @remark: !!!this function only can call after endFrame, then it's could be works well.
*/
static void readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& outbuffer);
static void readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, bool flipImage, PixelBufferDescriptor& outbuffer);
};
//end of _opengl group
/// @}