mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-21 23:45:58 +01:00
pointer: add drm dumb buffers for cursors (#8399)
--------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
parent
3fb47372b7
commit
20031cea92
8 changed files with 142 additions and 79 deletions
|
@ -103,7 +103,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||||
|
|
||||||
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4)
|
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4)
|
||||||
|
|
||||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.2)
|
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5)
|
||||||
|
|
||||||
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
|
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ if cpp_compiler.check_header('execinfo.h')
|
||||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
aquamarine = dependency('aquamarine', version: '>=0.4.2')
|
aquamarine = dependency('aquamarine', version: '>=0.4.5')
|
||||||
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
|
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
|
||||||
|
|
||||||
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||||
|
|
|
@ -571,7 +571,7 @@ CConfigManager::CConfigManager() {
|
||||||
m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{0});
|
||||||
|
|
||||||
m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0});
|
||||||
|
|
||||||
|
|
|
@ -375,6 +375,8 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||||
auto maxSize = state->monitor->output->cursorPlaneSize();
|
auto maxSize = state->monitor->output->cursorPlaneSize();
|
||||||
auto const& cursorSize = currentCursorImage.size;
|
auto const& cursorSize = currentCursorImage.size;
|
||||||
|
|
||||||
|
static auto PDUMB = CConfigValue<Hyprlang::INT>("cursor:use_cpu_buffer");
|
||||||
|
|
||||||
if (maxSize == Vector2D{})
|
if (maxSize == Vector2D{})
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -386,10 +388,23 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||||
} else
|
} else
|
||||||
maxSize = cursorSize;
|
maxSize = cursorSize;
|
||||||
|
|
||||||
if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size) {
|
if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size ||
|
||||||
|
*PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) {
|
||||||
|
|
||||||
if (!state->monitor->cursorSwapchain)
|
if (!state->monitor->cursorSwapchain || *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) {
|
||||||
state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(state->monitor->output->getBackend()->preferredAllocator(), state->monitor->output->getBackend());
|
|
||||||
|
auto allocator = state->monitor->output->getBackend()->preferredAllocator();
|
||||||
|
if (*PDUMB) {
|
||||||
|
for (const auto& a : state->monitor->output->getBackend()->getAllocators()) {
|
||||||
|
if (a->type() == Aquamarine::AQ_ALLOCATOR_TYPE_DRM_DUMB) {
|
||||||
|
allocator = a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state->monitor->cursorSwapchain = Aquamarine::CSwapchain::create(allocator, state->monitor->output->getBackend());
|
||||||
|
}
|
||||||
|
|
||||||
auto options = state->monitor->cursorSwapchain->currentOptions();
|
auto options = state->monitor->cursorSwapchain->currentOptions();
|
||||||
options.size = maxSize;
|
options.size = maxSize;
|
||||||
|
@ -397,8 +412,10 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||||
options.scanout = true;
|
options.scanout = true;
|
||||||
options.cursor = true;
|
options.cursor = true;
|
||||||
options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD;
|
options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD;
|
||||||
// We do not set the format. If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us,
|
// We do not set the format (unless shm). If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us,
|
||||||
// but if it's set, we don't wanna change it.
|
// but if it's set, we don't wanna change it.
|
||||||
|
if (*PDUMB)
|
||||||
|
options.format = DRM_FORMAT_ARGB8888;
|
||||||
|
|
||||||
if (!state->monitor->cursorSwapchain->reconfigure(options)) {
|
if (!state->monitor->cursorSwapchain->reconfigure(options)) {
|
||||||
Debug::log(TRACE, "Failed to reconfigure cursor swapchain");
|
Debug::log(TRACE, "Failed to reconfigure cursor swapchain");
|
||||||
|
@ -420,60 +437,69 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*PDUMB) {
|
||||||
|
// get the texture data if available.
|
||||||
|
auto texData = texture->dataCopy();
|
||||||
|
if (texData.empty()) {
|
||||||
|
if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) {
|
||||||
|
const auto SURFACE = currentCursorImage.surface->resource();
|
||||||
|
auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE);
|
||||||
|
|
||||||
|
bool flipRB = false;
|
||||||
|
|
||||||
|
if (SURFACE->current.texture) {
|
||||||
|
Debug::log(TRACE, "Cursor CPU surface: format {}, expecting AR24", FormatUtils::drmFormatName(SURFACE->current.texture->m_iDrmFormat));
|
||||||
|
if (SURFACE->current.texture->m_iDrmFormat == DRM_FORMAT_ABGR8888) {
|
||||||
|
Debug::log(TRACE, "Cursor CPU surface format AB24, will flip. WARNING: this will break on big endian!");
|
||||||
|
flipRB = true;
|
||||||
|
} else if (SURFACE->current.texture->m_iDrmFormat != DRM_FORMAT_ARGB8888) {
|
||||||
|
Debug::log(TRACE, "Cursor CPU surface format rejected, falling back to sw");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shmBuffer.data())
|
||||||
|
texData = shmBuffer;
|
||||||
|
else {
|
||||||
|
texData.resize(texture->m_vSize.x * 4 * texture->m_vSize.y);
|
||||||
|
memset(texData.data(), 0x00, texData.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flipRB) {
|
||||||
|
for (size_t i = 0; i < shmBuffer.size(); i += 4) {
|
||||||
|
std::swap(shmBuffer.at(i), shmBuffer.at(i + 2)); // little-endian!!!!!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then, we just yeet it into the dumb buffer
|
||||||
|
|
||||||
|
auto [data, fmt, size] = buf->beginDataPtr(0);
|
||||||
|
|
||||||
|
memset(data, 0, size);
|
||||||
|
if (buf->dmabuf().size.x > texture->m_vSize.x) {
|
||||||
|
size_t STRIDE = 4 * texture->m_vSize.x;
|
||||||
|
for (int i = 0; i < texture->m_vSize.y; i++)
|
||||||
|
memcpy(data + i * buf->dmabuf().strides[0], texData.data() + i * STRIDE, STRIDE);
|
||||||
|
} else
|
||||||
|
memcpy(data, texData.data(), std::min(size, texData.size()));
|
||||||
|
|
||||||
|
buf->endDataPtr();
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
g_pHyprRenderer->makeEGLCurrent();
|
||||||
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor;
|
g_pHyprOpenGL->m_RenderData.pMonitor = state->monitor;
|
||||||
|
|
||||||
auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format);
|
auto RBO = g_pHyprRenderer->getOrCreateRenderbuffer(buf, state->monitor->cursorSwapchain->currentOptions().format);
|
||||||
if (!RBO) {
|
if (!RBO) {
|
||||||
Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier);
|
Debug::log(TRACE, "Failed to create cursor RB with format {}, mod {}", buf->dmabuf().format, buf->dmabuf().modifier);
|
||||||
static auto PDUMB = CConfigValue<Hyprlang::INT>("cursor:allow_dumb_copy");
|
return nullptr;
|
||||||
if (!*PDUMB)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto bufData = buf->beginDataPtr(0);
|
|
||||||
auto bufPtr = std::get<0>(bufData);
|
|
||||||
|
|
||||||
// clear buffer
|
|
||||||
memset(bufPtr, 0, std::get<2>(bufData));
|
|
||||||
|
|
||||||
if (currentCursorImage.pBuffer) {
|
|
||||||
auto texAttrs = currentCursorImage.pBuffer->shm();
|
|
||||||
|
|
||||||
if (!texAttrs.success) {
|
|
||||||
Debug::log(TRACE, "Cannot use dumb copy on dmabuf cursor buffers");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto texData = currentCursorImage.pBuffer->beginDataPtr(GBM_BO_TRANSFER_WRITE);
|
|
||||||
auto texPtr = std::get<0>(texData);
|
|
||||||
Debug::log(TRACE, "cursor texture {}x{} {} {} {}", texAttrs.size.x, texAttrs.size.y, (void*)texPtr, texAttrs.format, texAttrs.stride);
|
|
||||||
// copy cursor texture
|
|
||||||
for (int i = 0; i < texAttrs.size.y; i++)
|
|
||||||
memcpy(bufPtr + i * buf->dmabuf().strides[0], texPtr + i * texAttrs.stride, texAttrs.stride);
|
|
||||||
} else if (currentCursorImage.surface && currentCursorImage.surface->resource()->role->role() == SURFACE_ROLE_CURSOR) {
|
|
||||||
const auto SURFACE = currentCursorImage.surface->resource();
|
|
||||||
auto& shmBuffer = CCursorSurfaceRole::cursorPixelData(SURFACE);
|
|
||||||
Debug::log(TRACE, "cursor texture pixel data length: {}B", shmBuffer.size());
|
|
||||||
|
|
||||||
if (shmBuffer.data()) {
|
|
||||||
// copy cursor texture
|
|
||||||
// assume format is 32bpp
|
|
||||||
size_t STRIDE = 4 * SURFACE->current.bufferSize.x;
|
|
||||||
for (int i = 0; i < SURFACE->current.bufferSize.y; i++)
|
|
||||||
memcpy(bufPtr + i * buf->dmabuf().strides[0], shmBuffer.data() + i * STRIDE, STRIDE);
|
|
||||||
} else {
|
|
||||||
// if there is no data, hide the cursor
|
|
||||||
memset(bufPtr, '\0', buf->size.x * buf->size.y * 4 /* assume 32bpp */);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Debug::log(TRACE, "Unsupported cursor buffer/surface, falling back to sw (can't dumb copy)");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->endDataPtr();
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RBO->bind();
|
RBO->bind();
|
||||||
|
@ -773,7 +799,7 @@ SP<CTexture> CPointerManager::getCurrentCursorTexture() {
|
||||||
|
|
||||||
if (currentCursorImage.pBuffer) {
|
if (currentCursorImage.pBuffer) {
|
||||||
if (!currentCursorImage.bufferTex)
|
if (!currentCursorImage.bufferTex)
|
||||||
currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBuffer);
|
currentCursorImage.bufferTex = makeShared<CTexture>(currentCursorImage.pBuffer, true);
|
||||||
return currentCursorImage.bufferTex;
|
return currentCursorImage.bufferTex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -438,12 +438,13 @@ void CWLSurfaceResource::commitPendingState() {
|
||||||
current.texture->m_eTransform = wlTransformToHyprutils(current.transform);
|
current.texture->m_eTransform = wlTransformToHyprutils(current.transform);
|
||||||
|
|
||||||
if (current.buffer && current.buffer->buffer) {
|
if (current.buffer && current.buffer->buffer) {
|
||||||
current.buffer->buffer->update(accumulateCurrentBufferDamage());
|
const auto DAMAGE = accumulateCurrentBufferDamage();
|
||||||
|
current.buffer->buffer->update(DAMAGE);
|
||||||
|
|
||||||
// if the surface is a cursor, update the shm buffer
|
// if the surface is a cursor, update the shm buffer
|
||||||
// TODO: don't update the entire texture
|
// TODO: don't update the entire texture
|
||||||
if (role->role() == SURFACE_ROLE_CURSOR)
|
if (role->role() == SURFACE_ROLE_CURSOR && !DAMAGE.empty())
|
||||||
updateCursorShm();
|
updateCursorShm(DAMAGE);
|
||||||
|
|
||||||
// release the buffer if it's synchronous as update() has done everything thats needed
|
// release the buffer if it's synchronous as update() has done everything thats needed
|
||||||
// so we can let the app know we're done.
|
// so we can let the app know we're done.
|
||||||
|
@ -486,13 +487,12 @@ void CWLSurfaceResource::commitPendingState() {
|
||||||
lastBuffer = current.buffer ? current.buffer->buffer : WP<IHLBuffer>{};
|
lastBuffer = current.buffer ? current.buffer->buffer : WP<IHLBuffer>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLSurfaceResource::updateCursorShm() {
|
void CWLSurfaceResource::updateCursorShm(CRegion damage) {
|
||||||
auto buf = current.buffer ? current.buffer->buffer : lastBuffer;
|
auto buf = current.buffer ? current.buffer->buffer : lastBuffer;
|
||||||
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: actually use damage
|
|
||||||
auto& shmData = CCursorSurfaceRole::cursorPixelData(self.lock());
|
auto& shmData = CCursorSurfaceRole::cursorPixelData(self.lock());
|
||||||
auto shmAttrs = buf->shm();
|
auto shmAttrs = buf->shm();
|
||||||
|
|
||||||
|
@ -501,11 +501,25 @@ void CWLSurfaceResource::updateCursorShm() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
damage.intersect(CBox{0, 0, buf->size.x, buf->size.y});
|
||||||
|
|
||||||
// no need to end, shm.
|
// no need to end, shm.
|
||||||
auto [pixelData, fmt, bufLen] = buf->beginDataPtr(0);
|
auto [pixelData, fmt, bufLen] = buf->beginDataPtr(0);
|
||||||
|
|
||||||
shmData.resize(bufLen);
|
shmData.resize(bufLen);
|
||||||
memcpy(shmData.data(), pixelData, bufLen);
|
|
||||||
|
if (const auto RECTS = damage.getRects(); RECTS.size() == 1 && RECTS.at(0).x2 == buf->size.x && RECTS.at(0).y2 == buf->size.y)
|
||||||
|
memcpy(shmData.data(), pixelData, bufLen);
|
||||||
|
else {
|
||||||
|
for (auto& box : damage.getRects()) {
|
||||||
|
for (auto y = box.y1; y < box.y2; ++y) {
|
||||||
|
// bpp is 32 INSALLAH
|
||||||
|
auto begin = 4 * box.y1 * (box.x2 - box.x1) + box.x1;
|
||||||
|
auto len = 4 * (box.x2 - box.x1);
|
||||||
|
memcpy((uint8_t*)shmData.data() + begin, (uint8_t*)pixelData + begin, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor) {
|
void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor) {
|
||||||
|
|
|
@ -148,7 +148,7 @@ class CWLSurfaceResource {
|
||||||
void dropCurrentBuffer();
|
void dropCurrentBuffer();
|
||||||
void commitPendingState();
|
void commitPendingState();
|
||||||
void bfHelper(std::vector<SP<CWLSurfaceResource>> const& nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
void bfHelper(std::vector<SP<CWLSurfaceResource>> const& nodes, std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
||||||
void updateCursorShm();
|
void updateCursorShm(CRegion damage = CBox{0, 0, INT16_MAX, INT16_MAX});
|
||||||
|
|
||||||
friend class CWLPointerResource;
|
friend class CWLPointerResource;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../protocols/types/Buffer.hpp"
|
#include "../protocols/types/Buffer.hpp"
|
||||||
#include "../helpers/Format.hpp"
|
#include "../helpers/Format.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
CTexture::CTexture() {
|
CTexture::CTexture() {
|
||||||
// naffin'
|
// naffin'
|
||||||
|
@ -16,7 +17,7 @@ CTexture::~CTexture() {
|
||||||
destroyTexture();
|
destroyTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) {
|
CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_, bool keepDataCopy) : m_iDrmFormat(drmFormat), m_bKeepDataCopy(keepDataCopy) {
|
||||||
createFromShm(drmFormat, pixels, stride, size_);
|
createFromShm(drmFormat, pixels, stride, size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) {
|
||||||
createFromDma(attrs, image);
|
createFromDma(attrs, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTexture::CTexture(const SP<Aquamarine::IBuffer> buffer) {
|
CTexture::CTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy) : m_bKeepDataCopy(keepDataCopy) {
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -43,6 +44,8 @@ CTexture::CTexture(const SP<Aquamarine::IBuffer> buffer) {
|
||||||
|
|
||||||
auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0);
|
auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0);
|
||||||
|
|
||||||
|
m_iDrmFormat = fmt;
|
||||||
|
|
||||||
createFromShm(fmt, pixelData, bufLen, shm.size);
|
createFromShm(fmt, pixelData, bufLen, shm.size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +83,11 @@ void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t strid
|
||||||
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels));
|
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels));
|
||||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
||||||
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
|
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||||
|
|
||||||
|
if (m_bKeepDataCopy) {
|
||||||
|
m_vDataCopy.resize(stride * size_.y);
|
||||||
|
memcpy(m_vDataCopy.data(), pixels, stride * size_.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) {
|
void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) {
|
||||||
|
@ -135,6 +143,11 @@ void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, cons
|
||||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
|
GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
if (m_bKeepDataCopy) {
|
||||||
|
m_vDataCopy.resize(stride * m_vSize.y);
|
||||||
|
memcpy(m_vDataCopy.data(), pixels, stride * m_vSize.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTexture::destroyTexture() {
|
void CTexture::destroyTexture() {
|
||||||
|
@ -152,3 +165,7 @@ void CTexture::allocate() {
|
||||||
if (!m_iTexID)
|
if (!m_iTexID)
|
||||||
GLCALL(glGenTextures(1, &m_iTexID));
|
GLCALL(glGenTextures(1, &m_iTexID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<uint8_t>& CTexture::dataCopy() {
|
||||||
|
return m_vDataCopy;
|
||||||
|
}
|
||||||
|
|
|
@ -24,26 +24,32 @@ class CTexture {
|
||||||
CTexture(const CTexture&&) = delete;
|
CTexture(const CTexture&&) = delete;
|
||||||
CTexture(const CTexture&) = delete;
|
CTexture(const CTexture&) = delete;
|
||||||
|
|
||||||
CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false);
|
||||||
|
|
||||||
CTexture(const SP<Aquamarine::IBuffer> buffer);
|
CTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy = false);
|
||||||
// this ctor takes ownership of the eglImage.
|
// this ctor takes ownership of the eglImage.
|
||||||
CTexture(const Aquamarine::SDMABUFAttrs&, void* image);
|
CTexture(const Aquamarine::SDMABUFAttrs&, void* image);
|
||||||
~CTexture();
|
~CTexture();
|
||||||
|
|
||||||
void destroyTexture();
|
void destroyTexture();
|
||||||
void allocate();
|
void allocate();
|
||||||
void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage);
|
void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage);
|
||||||
|
const std::vector<uint8_t>& dataCopy();
|
||||||
|
|
||||||
TEXTURETYPE m_iType = TEXTURE_RGBA;
|
TEXTURETYPE m_iType = TEXTURE_RGBA;
|
||||||
GLenum m_iTarget = GL_TEXTURE_2D;
|
GLenum m_iTarget = GL_TEXTURE_2D;
|
||||||
GLuint m_iTexID = 0;
|
GLuint m_iTexID = 0;
|
||||||
Vector2D m_vSize = {};
|
Vector2D m_vSize = {};
|
||||||
void* m_pEglImage = nullptr;
|
void* m_pEglImage = nullptr;
|
||||||
eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL;
|
eTransform m_eTransform = HYPRUTILS_TRANSFORM_NORMAL;
|
||||||
bool m_bOpaque = false;
|
bool m_bOpaque = false;
|
||||||
|
uint32_t m_iDrmFormat = 0; // for shm
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
||||||
void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image);
|
void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image);
|
||||||
|
|
||||||
|
bool m_bKeepDataCopy = false;
|
||||||
|
|
||||||
|
std::vector<uint8_t> m_vDataCopy;
|
||||||
};
|
};
|
Loading…
Reference in a new issue