提交 eaa35b1d 编写于 作者: Z ZhaoPengyuan

memory:delay the deletion of ColorBuffers

delete the ColorBuffers which not used within 2 seconds
上级 416a3daf
......@@ -102,7 +102,7 @@ class ScopedHelperContext {
// static
ColorBuffer* ColorBuffer::create(EGLDisplay p_display, int p_width,
int p_height, GLenum p_internalFormat,
bool has_eglimage_texture_2d, Helper* helper) {
bool has_eglimage_texture_2d, Helper* helper, HandleType hndl) {
GLenum texInternalFormat = 0;
switch (p_internalFormat) {
......@@ -127,7 +127,7 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display, int p_width,
return NULL;
}
ColorBuffer* cb = new ColorBuffer(p_display, helper);
ColorBuffer* cb = new ColorBuffer(p_display, helper, hndl);
s_gles2.glGenTextures(1, &cb->m_tex);
s_gles2.glBindTexture(GL_TEXTURE_2D, cb->m_tex);
......@@ -176,7 +176,7 @@ ColorBuffer* ColorBuffer::create(EGLDisplay p_display, int p_width,
return cb;
}
ColorBuffer::ColorBuffer(EGLDisplay display, Helper* helper)
ColorBuffer::ColorBuffer(EGLDisplay display, Helper* helper, HandleType hndl)
: m_tex(0),
m_blitTex(0),
m_eglImage(NULL),
......@@ -184,7 +184,8 @@ ColorBuffer::ColorBuffer(EGLDisplay display, Helper* helper)
m_fbo(0),
m_internalFormat(0),
m_display(display),
m_helper(helper) {}
m_helper(helper),
mHndl(hndl) {}
ColorBuffer::~ColorBuffer() {
ScopedHelperContext context(m_helper);
......@@ -206,6 +207,10 @@ ColorBuffer::~ColorBuffer() {
delete m_resizer;
}
HandleType ColorBuffer::getHndl() const {
return mHndl;
}
void ColorBuffer::readPixels(int x, int y, int width, int height,
GLenum p_format, GLenum p_type, void* pixels) {
ScopedHelperContext context(m_helper);
......
......@@ -22,6 +22,8 @@
#include <memory>
typedef uint32_t HandleType;
class TextureDraw;
class TextureResize;
......@@ -77,7 +79,7 @@ class ColorBuffer {
// Returns NULL on failure.
static ColorBuffer* create(EGLDisplay p_display, int p_width, int p_height,
GLenum p_internalFormat,
bool has_eglimage_texture_2d, Helper* helper);
bool has_eglimage_texture_2d, Helper* helper, HandleType hndl);
// Destructor.
~ColorBuffer();
......@@ -115,10 +117,12 @@ class ColorBuffer {
void bind();
HandleType getHndl() const;
private:
ColorBuffer(); // no default constructor.
explicit ColorBuffer(EGLDisplay display, Helper* helper);
explicit ColorBuffer(EGLDisplay display, Helper* helper, HandleType hndl);
private:
GLuint m_tex;
......@@ -132,6 +136,7 @@ class ColorBuffer {
EGLDisplay m_display;
Helper* m_helper;
TextureResize* m_resizer;
HandleType mHndl;
};
typedef std::shared_ptr<ColorBuffer> ColorBufferPtr;
......
......@@ -28,7 +28,6 @@
#include <set>
typedef uint32_t HandleType;
typedef std::set<HandleType> ThreadContextSet;
typedef std::set<HandleType> WindowSurfaceSet;
......
......@@ -27,6 +27,8 @@
#include "gles2_dec.h"
#include <stdio.h>
#include <cstdint>
#include <chrono>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
......@@ -35,6 +37,12 @@
#include <glm/gtx/transform.hpp>
#pragma GCC diagnostic pop
int64_t getCurrentLocalTimeStamp()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
namespace {
// Helper class to call the bind_locked() / unbind_locked() properly.
......@@ -84,10 +92,16 @@ class ColorBufferHelper : public ColorBuffer::Helper {
};
} // namespace
void Renderer::saveColorBuffer(ColorBufferRef* cbRef) {
eraseDelayedCloseColorBufferLocked(cbRef->cb->getHndl(), cbRef->closedTs);
cbRef->closedTs = 0;
}
HandleType Renderer::s_nextHandle = 0;
void Renderer::finalize() {
m_colorbuffers.clear();
m_colorBufferDelayedCloseList.clear();
m_windows.clear();
m_contexts.clear();
s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL);
......@@ -366,14 +380,15 @@ HandleType Renderer::createColorBuffer(int p_width, int p_height,
std::unique_lock<std::mutex> l(m_lock);
HandleType ret = 0;
ret = genHandle();
ColorBufferPtr cb(ColorBuffer::create(
getDisplay(), p_width, p_height, p_internalFormat,
getCaps().has_eglimage_texture_2d, m_colorBufferHelper));
getCaps().has_eglimage_texture_2d, m_colorBufferHelper, ret));
if (cb) {
ret = genHandle();
m_colorbuffers[ret].cb = cb;
m_colorbuffers[ret].refcount = 1;
m_colorbuffers[ret].closedTs= 0;
RenderThreadInfo *tInfo = RenderThreadInfo::get();
if (!tInfo) {
......@@ -475,12 +490,7 @@ void Renderer::drainWindowSurface() {
if (m_windows.find(windowHandle) != m_windows.end()) {
HandleType oldColorBufferHandle = m_windows[windowHandle].second;
if (oldColorBufferHandle) {
ColorBufferMap::iterator cit(m_colorbuffers.find(oldColorBufferHandle));
if (cit != m_colorbuffers.end()) {
if (--(*cit).second.refcount == 0) {
m_colorbuffers.erase(cit);
}
}
closeColorBufferLocked(oldColorBufferHandle);
}
m_windows.erase(windowHandle);
}
......@@ -511,11 +521,12 @@ void Renderer::DestroyRenderContext(HandleType p_context) {
void Renderer::DestroyWindowSurface(HandleType p_surface) {
std::unique_lock<std::mutex> l(m_lock);
if (m_windows.find(p_surface) != m_windows.end()) {
m_windows.erase(p_surface);
RenderThreadInfo *tinfo = RenderThreadInfo::get();
if (tinfo->m_windowSet.empty()) return;
tinfo->m_windowSet.erase(p_surface);
const auto w = m_windows.find(p_surface);
if (w != m_windows.end()) {
closeColorBufferLocked(w->second.second);
m_windows.erase(w);
RenderThreadInfo* tinfo = RenderThreadInfo::get();
tinfo->m_windowSet.erase(p_surface);
}
}
......@@ -530,6 +541,7 @@ int Renderer::openColorBuffer(HandleType p_colorbuffer) {
return -1;
}
(*c).second.refcount++;
saveColorBuffer(&c->second);
int tid = tInfo->m_tid;
if (tid > 0) {
m_procOwnedColorBuffers[tid].insert(p_colorbuffer);
......@@ -537,6 +549,51 @@ int Renderer::openColorBuffer(HandleType p_colorbuffer) {
return 0;
}
void Renderer::eraseDelayedCloseColorBufferLocked(HandleType cb, int64_t ts) {
// Find the first delayed buffer with a timestamp <= |ts|
auto it = std::lower_bound(
m_colorBufferDelayedCloseList.begin(),
m_colorBufferDelayedCloseList.end(), ts,
[](const ColorBufferCloseInfo& ci, int64_t ts) {
return ci.ts < ts;
});
while (it != m_colorBufferDelayedCloseList.end() &&
it->ts == ts) {
// if this is the one we need - clear it out.
if (it->cbHandle == cb) {
it->cbHandle = 0;
break;
}
++it;
}
}
void Renderer::performDelayedColorBufferCloseLocked() {
// Let's wait just long enough to make sure it's not because of instant
// timestamp change (end of previous second -> beginning of a next one),
// but not for long - this is a workaround for race conditions, and they
// are quick.
static constexpr int64_t kColorBufferClosingDelayMS = 2000;
const auto now = getCurrentLocalTimeStamp();
auto it = m_colorBufferDelayedCloseList.begin();
while (it != m_colorBufferDelayedCloseList.end() &&
(it->ts + kColorBufferClosingDelayMS <= now)) {
if (it->cbHandle != 0) {
for (auto& ite : m_procOwnedColorBuffers) {
if (ite.second.find(it->cbHandle) != ite.second.end()) {
ite.second.erase(it->cbHandle);
}
}
const auto& cb = m_colorbuffers.find(it->cbHandle);
m_colorbuffers.erase(cb);
}
++it;
}
m_colorBufferDelayedCloseList.erase(
m_colorBufferDelayedCloseList.begin(), it);
}
void Renderer::closeColorBufferLocked(HandleType p_colorbuffer) {
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
if (c == m_colorbuffers.end()) {
......@@ -547,8 +604,11 @@ void Renderer::closeColorBufferLocked(HandleType p_colorbuffer) {
return;
}
if (--(*c).second.refcount == 0) {
m_colorbuffers.erase(c);
c->second.closedTs = getCurrentLocalTimeStamp();
m_colorBufferDelayedCloseList.push_back(
{c->second.closedTs, p_colorbuffer});
}
performDelayedColorBufferCloseLocked();
}
void Renderer::closeColorBuffer(HandleType p_colorbuffer)
......@@ -649,6 +709,11 @@ bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
}
(*w).second.first->setColorBuffer((*c).second.cb);
saveColorBuffer(&c->second);
if (w->second.second) {
closeColorBufferLocked(w->second.second);
}
c->second.refcount++;
(*w).second.second = p_colorbuffer;
return true;
}
......
......@@ -44,6 +44,7 @@ typedef uint32_t HandleType;
struct ColorBufferRef {
ColorBufferPtr cb;
uint32_t refcount; // number of client-side references
int64_t closedTs;
};
typedef std::map<HandleType, RenderContextPtr> RenderContextMap;
typedef std::unordered_set<HandleType> RenderContextSet;
......@@ -87,6 +88,12 @@ class Renderer : public anbox::graphics::Renderer {
Renderer();
virtual ~Renderer();
void saveColorBuffer(ColorBufferRef* cbRef);
void eraseDelayedCloseColorBufferLocked(HandleType cb, int64_t ts);
void performDelayedColorBufferCloseLocked();
// Initialize the global instance.
// |width| and |height| are the dimensions of the emulator GPU display
// in pixels. |useSubWindow| is true to indicate that the caller
......@@ -171,9 +178,9 @@ class Renderer : public anbox::graphics::Renderer {
// createColorBuffer(). Note that if the reference count reaches 0,
// the instance is destroyed automatically.
void closeColorBuffer(HandleType p_colorbuffer);
void closeColorBufferLocked(HandleType p_colorbuffer);
void closeColorBufferLocked(HandleType p_colorbuffer);
void cleanupProcGLObjects(int tid);
void cleanupProcGLObjects(int tid);
// Equivalent for eglMakeCurrent() for the current display.
// |p_context|, |p_drawSurface| and |p_readSurface| are the handle values
// of the context, the draw surface and the read surface, respectively.
......@@ -326,5 +333,21 @@ class Renderer : public anbox::graphics::Renderer {
ProcOwnedColorBuffers m_procOwnedColorBuffers;
ProcOwnedEGLImages m_procOwnedEGLImages;
ProcOwnedRenderContexts m_procOwnedRenderContext;
// A collection of color buffers that were closed without any usages
//
// If a buffer reached |refcount| == 0 while not being |opened|, instead of
// deleting it we remember the timestamp when this happened. Later, we
// check if the buffer stayed unopened long enough and if it did, we delete
// it permanently. On the other hand, if the color buffer was used then
// we don't care about timestamps anymore.
//
// Note: this collection is ordered by |ts| field.
struct ColorBufferCloseInfo {
int64_t ts; // when we got the close request.
HandleType cbHandle; // 0 == already closed, do nothing
};
using ColorBufferDelayedClose = std::vector<ColorBufferCloseInfo>;
ColorBufferDelayedClose m_colorBufferDelayedCloseList;
};
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册