SDL2 рендеринг в текстуру

Мое приложение имеет несколько представлений, которые используют свои собственные SDL_Window а также SDL_Rendererиспользование средства визуализации для отрисовки всех моих слоев листов в главном виде (основной вид содержит комбинированный результат рендеринга нескольких слоев листов, а другие представления предназначены для отображения каждого отдельного слоя в «панели слоев» в стиле фотошопа). ). Проблема здесь заключается в попытке взять текстуру (или поверхность, рендерер и т. Д.) И отобразить ее в другом автономном представлении. Если я использую SetRenderTarget а также SDL_RenderCopy, он терпит неудачу, потому что целевая текстура принадлежит другому рендереру …

Я также пытался заблокировать пиксели текстуры каждого вида, пытаясь вручную скопировать пиксели, но заблокировать пиксели не удалось, если текстура не была создана как потоковая текстура … Кроме того, представления имеют разные размеры, поэтому целевую текстуру нужно будет растянуть, чтобы она соответствовала, вызывая больше работы, чем необходимо.

Это привело меня к использованию SDL_SoftStretch… который работает, но, конечно, болезненно медленный, так как не может использоваться с аппаратно ускоренными текстурами.

Существует ли какой-либо правдоподобный, достаточно эффективный способ получения результата одного SDL_Windowи рендеринг уменьшенной версии его версии в другую?


РЕДАКТИРОВАТЬ:
Помимо тесного использования SDL_SoftStretch, это самое близкое, что я пришел, чтобы заставить вещи работать …
Это терпит неудачу, потому что я ударил другую кирпичную стену, когда искал способ получить данные о пикселях от рендерера:

SDLView.cpp

//...
BOOL SDLView::Init()
{
m_sdlWindow = SDL_CreateWindowFrom( (PVOID)m_hWndParent );
if(m_sdlWindow == NULL)
return false;

m_sdlRenderer = SDL_CreateRenderer(m_sdlWindow, -1, SDL_RendererFlags::SDL_RENDERER_ACCELERATED);
if(m_sdlRenderer == NULL)
return false;

memset(&m_rect, 0, sizeof(SDL_Rect));
SDL_GetRendererOutputSize(m_sdlRenderer, &m_rect.w, &m_rect.h);
m_pixelFormat = SDL_GetWindowPixelFormat(m_sdlWindow);
m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, m_pixelFormat, SDL_TEXTUREACCESS_STREAMING, m_rect.w, m_rect.h);

SDL_SetRenderDrawColor(m_sdlRenderer, 0x64, 0x95, 0xED, 0xFF);

return true;
}

BOOL SDLView::Clear()
{
memset(&m_rect, 0, sizeof(SDL_Rect));
SDL_GetRendererOutputSize(m_sdlRenderer, &m_rect.w, &m_rect.h);
return SDL_RenderClear(m_sdlRenderer) == 0;
}

VOID SDLView::Present()
{
// Doesn't work because we still have no way of grabbing the rendered output!!
SDL_RenderPresent(m_sdlRenderer);
int result = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, NULL);
if(result != 0) {
std::string err(SDL_GetError());
DebugBreak();
}
}

LayerListItem.cpp

void CLayerListItem::OnPaint()
{
CWnd::OnPaint();
CRect rc;
GetClientRect(&rc);

if(m_destView != nullptr)
{
m_destView->Clear();
if(m_srcView != nullptr)
{
int srcPitch = 0, destPitch = 0;
void *srcPixels = nullptr, *destPixels = nullptr;

// Lock the source pixels
int ret = SDL_LockTexture(m_srcView->GetTexture(), &m_srcView->GetRect(), &srcPixels, &srcPitch);
if(ret != 0) {
std::string err(SDL_GetError());
DebugBreak();
}
// Lock the destination pixels
ret = SDL_LockTexture(m_destView->GetTexture(), &m_destView->GetRect(), &destPixels, &destPitch);
if(ret != 0) {
std::string err(SDL_GetError());
DebugBreak();
}

// Unlock all pixels
SDL_UnlockTexture(m_destView->GetTexture());
SDL_UnlockTexture(m_srcView->GetTexture());

// Update our destinaition texture
// (I have tried every possible combination for this line, still no dice!)
int result = SDL_UpdateTexture(
m_destView->GetTexture(),
&m_destView->GetRect(),
srcPixels, srcPitch
);
if(ret != 0) {
std::string err(SDL_GetError());
DebugBreak();
}
SDL_RenderCopy(m_destView->GetRenderer(), m_destView->GetTexture(), NULL, NULL);

OutputDebugStringA("[RENDERED!]...\n");
}
m_destView->Present();
}
}

Каждое несколько секунд отправляется событие OnPaint, которое в свою очередь пытается получить обработанный вывод и сохранить его в m_destView (который, как m_srcView, является SDLView). В лучшем случае это приводит к правильно отображаемому основному виду («исходному виду»), но к цели как к черному. У меня такое чувство, что я уже все перепробовал, разве что-то помимо того, что я уже пробовал … есть идеи?

0

Решение

Я вроде, как бы, что-то вроде решил это, используя несколько медленно — (все же, все же лучше, чем SDL_SoftRect) — функция SDL_RenderReadPixels:

VOID SDLView::CopyTo(SDLView *targetView)
{
int result = SDL_RenderReadPixels(m_sdlRenderer, nullptr, m_pixelFormat, m_sdlSurface->pixels, m_sdlSurface->pitch);
if(result != 0) {
std::string err(SDL_GetError());
OutputDebugStringA(err.c_str());
return;
}

SDL_Texture *destTexture = targetView->GetTexture();
result = SDL_UpdateTexture(destTexture, nullptr, m_sdlSurface->pixels, m_sdlSurface->pitch);
if(result != 0) {
std::string err(SDL_GetError());
OutputDebugStringA(err.c_str());
return;
}
}

Хорошо работает в паре с m_sdlSurface = SDL_GetWindowSurface(m_sdlWindow) так же как m_pixelFormat = SDL_GetWindowPixelFormat(m_sdlWindow)

Тем не менее, обратите внимание, что это НЕ помогает при уменьшении изображения, что, вероятно, означает, что мне все равно нужно будет использовать RenderCopyEx или эквивалент в какой-то момент перед предоставлением окончательного изображения в пункт назначения.
Но пока я отмечу это как ответ, пока кто-то не сможет предложить лучшее решение.

1

Другие решения


По вопросам рекламы [email protected]