diff --git a/cocos/base/ccUtils.cpp b/cocos/base/ccUtils.cpp index f02c76d6b4..078739e6a9 100644 --- a/cocos/base/ccUtils.cpp +++ b/cocos/base/ccUtils.cpp @@ -28,6 +28,7 @@ THE SOFTWARE. #include #include "base/CCDirector.h" +#include "base/CCAsyncTaskPool.h" #include "renderer/CCCustomCommand.h" #include "renderer/CCRenderer.h" #include "platform/CCImage.h" @@ -49,22 +50,39 @@ int ccNextPOT(int x) namespace utils { /** - * Capture screen implementation, don't use it directly. - */ +* Capture screen implementation, don't use it directly. +*/ void onCaptureScreen(const std::function& afterCaptured, const std::string& filename) { + static bool startedCapture = false; + + if (startedCapture) + { + CCLOG("Screen capture is already working"); + if (afterCaptured) + { + afterCaptured(false, filename); + } + return; + } + else + { + startedCapture = true; + } + + auto glView = Director::getInstance()->getOpenGLView(); auto frameSize = glView->getFrameSize(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX) frameSize = frameSize * glView->getFrameZoomFactor() * glView->getRetinaFactor(); #endif - + int width = static_cast(frameSize.width); int height = static_cast(frameSize.height); - + bool succeed = false; std::string outputFile = ""; - + do { std::shared_ptr buffer(new GLubyte[width * height * 4], [](GLubyte* p){ CC_SAFE_DELETE_ARRAY(p); }); @@ -72,10 +90,10 @@ void onCaptureScreen(const std::function& afterC { break; } - + glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get()); - + std::shared_ptr flippedBuffer(new GLubyte[width * height * 4], [](GLubyte* p) { CC_SAFE_DELETE_ARRAY(p); }); if (!flippedBuffer) { @@ -87,7 +105,7 @@ void onCaptureScreen(const std::function& afterC memcpy(flippedBuffer.get() + (height - row - 1) * width * 4, buffer.get() + row * width * 4, width * 4); } - std::shared_ptr image(new Image); + Image* image = new (std::nothrow) Image; if (image) { image->initWithRawData(flippedBuffer.get(), width * height * 4, width, height, 8); @@ -100,15 +118,36 @@ void onCaptureScreen(const std::function& afterC CCASSERT(filename.find("/") == std::string::npos, "The existence of a relative path is not guaranteed!"); outputFile = FileUtils::getInstance()->getWritablePath() + filename; } - succeed = image->saveToFile(outputFile); + + // Save image in AsyncTaskPool::TaskType::TASK_IO thread, and call afterCaptured in mainThread + static bool succeedSaveToFile = false; + std::function mainThread = [afterCaptured, outputFile](void* param) + { + if (afterCaptured) + { + afterCaptured(succeedSaveToFile, outputFile); + } + startedCapture = false; + }; + + AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_IO, mainThread, (void*)NULL, [image, outputFile]() + { + succeedSaveToFile = image->saveToFile(outputFile); + delete image; + }); } - }while(0); - - if (afterCaptured) - { - afterCaptured(succeed, outputFile); - } + else + { + CCLOG("Malloc Image memory failed!"); + if (afterCaptured) + { + afterCaptured(succeed, outputFile); + } + startedCapture = false; + } + } while (0); } + /* * Capture screen interface */