Skip to content

Commit

Permalink
UPBGE: Fix Texture mipmap with ImageRender.
Browse files Browse the repository at this point in the history
In VideoTexture module, the source can behave in two way:
they return a pointer on a pixel array computed in CPU or
copy a OpenGL texture to the provided bind code.

In the first case the data send to a OpenGL texture work and
detect mipmap and generate them.
In the sceond case the mipmap are just forgotten...

So to fix this issue the calcViewport function, the only function
doing texture to texture copy receive the mipmap settings.
This settings help to generate texture seting for mipmapping
in loadTexture and to call glGenerateMipmap after calling
glCopyTexSubImage2D.
In consideration the caller of calcViewport: getImage, calcImage
have to accept the mipmap argument too.

Fix issue: #528.
  • Loading branch information
panzergame committed Aug 11, 2017
1 parent b653f9a commit 0d5c77e
Show file tree
Hide file tree
Showing 16 changed files with 49 additions and 40 deletions.
8 changes: 4 additions & 4 deletions source/gameengine/VideoTexture/DeckLink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,12 +550,12 @@ static PyObject *DeckLink_refresh(DeckLink *self, PyObject *args)
if (srcSize[0] == self->mSize[0] && srcSize[1] == self->mSize[1])
{
// buffer has same size, can load directly
if (!leftImage->loadImage(leftEye, self->mFrameSize, GL_BGRA, ts))
if (!leftImage->loadImage(leftEye, self->mFrameSize, false, GL_BGRA, ts))
leftEye = nullptr;
}
else {
// scaling is required, go the hard way
unsigned int *src = leftImage->getImage(0, ts);
unsigned int *src = leftImage->getImage(0, ts, false);
if (src != nullptr)
decklink_ConvImage(leftEye, self->mSize, src, srcSize, self->mUseExtend);
else
Expand All @@ -570,11 +570,11 @@ static PyObject *DeckLink_refresh(DeckLink *self, PyObject *args)
if (srcSize[0] == self->mSize[0] && srcSize[1] == self->mSize[1])
{
// buffer has same size, can load directly
rightImage->loadImage(rightEye, self->mFrameSize, GL_BGRA, ts);
rightImage->loadImage(rightEye, self->mFrameSize, false, GL_BGRA, ts);
}
else {
// scaling is required, go the hard way
unsigned int *src = rightImage->getImage(0, ts);
unsigned int *src = rightImage->getImage(0, ts, false);
if (src != nullptr)
decklink_ConvImage(rightEye, self->mSize, src, srcSize, self->mUseExtend);
}
Expand Down
20 changes: 10 additions & 10 deletions source/gameengine/VideoTexture/ImageBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ bool ImageBase::release (void)


// get image
unsigned int * ImageBase::getImage (unsigned int texId, double ts)
unsigned int * ImageBase::getImage (unsigned int texId, double ts, bool mipmap)
{
// if image is not available
if (!m_avail)
Expand All @@ -111,21 +111,21 @@ unsigned int * ImageBase::getImage (unsigned int texId, double ts)
// get images from sources
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
// get source image
(*it)->getImage(ts);
(*it)->getImage(ts, mipmap);
// init image
init(m_sources[0]->getSize()[0], m_sources[0]->getSize()[1]);
}
// calculate new image
calcImage(texId, ts);
calcImage(texId, ts, mipmap, m_internalFormat);
}
// if image is available, return it, otherwise nullptr
return m_avail ? m_image : nullptr;
}

bool ImageBase::loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts)
bool ImageBase::loadImage(unsigned int *buffer, unsigned int size, bool mipmap, unsigned int format, double ts)
{
unsigned int *d, *s, v, len;
if (getImage(0, ts) != nullptr && size >= getBuffSize()) {
if (getImage(0, ts, mipmap) != nullptr && size >= getBuffSize()) {
switch (format) {
case GL_RGBA:
memcpy(buffer, m_image, getBuffSize());
Expand Down Expand Up @@ -373,12 +373,12 @@ void ImageSource::setSource (PyImage *source)


// get image from source
unsigned int * ImageSource::getImage (double ts)
unsigned int * ImageSource::getImage (double ts, bool mipmap)
{
// if source is available
if (m_source != nullptr)
// get image from source
m_image = m_source->m_image->getImage(0, ts);
m_image = m_source->m_image->getImage(0, ts, mipmap);
// otherwise reset buffer
else
m_image = nullptr;
Expand Down Expand Up @@ -438,7 +438,7 @@ PyObject *Image_getImage(PyImage *self, char *mode)
{
try
{
unsigned int * image = self->m_image->getImage();
unsigned int * image = self->m_image->getImage(0, -1.0, false);
if (image)
{
// build BGL buffer
Expand Down Expand Up @@ -571,7 +571,7 @@ PyObject *Image_refresh (PyImage *self, PyObject *args)
else
THRWEXCP(InvalidImageMode,S_OK);

done = self->m_image->loadImage((unsigned int *)buffer.buf, buffer.len, format, ts);
done = self->m_image->loadImage((unsigned int *)buffer.buf, buffer.len, false, format, ts);
}
catch (Exception & exp) {
exp.report();
Expand Down Expand Up @@ -802,7 +802,7 @@ static int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)

try {
// can throw in case of resize
image = self->m_image->getImage();
image = self->m_image->getImage(0, -1.0, false);
}
catch (Exception & exp) {
exp.report();
Expand Down
8 changes: 4 additions & 4 deletions source/gameengine/VideoTexture/ImageBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class ImageBase
bool isImageAvailable(void)
{ return m_avail; }
/// get image
unsigned int *getImage(unsigned int texId = 0, double timestamp=-1.0);
unsigned int *getImage(unsigned int texId, double timestamp, bool mipmap);
/// get image size
short * getSize(void) { return m_size; }

Expand Down Expand Up @@ -112,7 +112,7 @@ class ImageBase

/// calculate image from sources and send it to a target buffer instead of a texture
/// format is GL_RGBA or GL_BGRA
virtual bool loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts);
virtual bool loadImage(unsigned int *buffer, unsigned int size, bool mipmap, unsigned int format, double ts);

/// swap the B and R channel in-place in the image buffer
void swapImageBR();
Expand Down Expand Up @@ -164,7 +164,7 @@ class ImageBase
bool checkSourceSizes(void);

/// calculate image from sources and set its availability
virtual void calcImage(unsigned int texId, double ts) {}
virtual void calcImage(unsigned int texId, double ts, bool mipmap, unsigned int format) {}

/// perform loop detection
bool loopDetect(ImageBase * img);
Expand Down Expand Up @@ -310,7 +310,7 @@ class ImageSource
void setSource (PyImage *source);

/// get image from source
unsigned int * getImage (double ts=-1.0);
unsigned int * getImage (double ts, bool mipmap);
/// get buffered image
unsigned int * getImageBuf (void) { return m_image; }
/// refresh source
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/VideoTexture/ImageMix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ ExceptionID ImageSizesNotMatch;
ExpDesc ImageSizesNotMatchDesc(ImageSizesNotMatch, "Image sizes of sources are different");

// calculate image from sources and set its availability
void ImageMix::calcImage(unsigned int texId, double ts)
void ImageMix::calcImage(unsigned int texId, double ts, bool mipmap, unsigned int format)
{
// check source sizes
if (!checkSourceSizes()) THRWEXCP(ImageSizesNotMatch, S_OK);
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/VideoTexture/ImageMix.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class ImageMix : public ImageBase
virtual ImageSource *newSource(const char *id) { return new ImageSourceMix(id); }

/// calculate image from sources and set its availability
virtual void calcImage (unsigned int texId, double ts);
virtual void calcImage (unsigned int texId, double ts, bool mipmap, unsigned int format);
};


Expand Down
4 changes: 2 additions & 2 deletions source/gameengine/VideoTexture/ImageRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ void ImageRender::setZenithFromScene(KX_Scene *scene)
}

// capture image from viewport
void ImageRender::calcViewport (unsigned int texId, double ts, unsigned int format)
void ImageRender::calcViewport (unsigned int texId, double ts, bool mipmap, unsigned int format)
{
// render the scene from the camera
if (!m_done) {
Expand All @@ -213,7 +213,7 @@ void ImageRender::calcViewport (unsigned int texId, double ts, unsigned int form
// wait until all render operations are completed
WaitSync();
// get image from viewport (or FBO)
ImageViewport::calcViewport(texId, ts, format);
ImageViewport::calcViewport(texId, ts, mipmap, format);

RAS_OffScreen::RestoreScreen();
}
Expand Down
7 changes: 5 additions & 2 deletions source/gameengine/VideoTexture/ImageRender.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,13 @@ class ImageRender : public ImageViewport
MT_Vector4 m_zenith;

/// render 3d scene to image
virtual void calcImage (unsigned int texId, double ts, unsigned int format) { calcViewport(texId, ts, format); }
virtual void calcImage (unsigned int texId, double ts, bool mipmap, unsigned int format)
{
calcViewport(texId, ts, mipmap, format);
}

/// render 3d scene to image
virtual void calcViewport (unsigned int texId, double ts, unsigned int format);
virtual void calcViewport (unsigned int texId, double ts, bool mipmap, unsigned int format);

void setHorizonFromScene(KX_Scene *scene);
void setZenithFromScene(KX_Scene *scene);
Expand Down
13 changes: 8 additions & 5 deletions source/gameengine/VideoTexture/ImageViewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void ImageViewport::setPosition (GLint pos[2])


// capture image from viewport
void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int format)
void ImageViewport::calcViewport (unsigned int texId, double ts, bool mipmap, unsigned int format)
{
// if scale was changed
if (m_scaleChange)
Expand All @@ -167,7 +167,7 @@ void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int fo
// if texture wasn't initialized
if (!m_texInit && texId != 0) {
// initialize it
loadTexture(texId, m_image, m_size, false, m_internalFormat);
loadTexture(texId, m_image, m_size, mipmap, m_internalFormat);
m_texInit = true;
}
// if texture can be directly created
Expand All @@ -177,6 +177,9 @@ void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int fo
// just copy current viewport to texture
glBindTexture(GL_TEXTURE_2D, texId);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1]);
if (mipmap) {
glGenerateMipmap(GL_TEXTURE_2D);
}
glBindTexture(GL_TEXTURE_2D, 0);
// image is not available
m_avail = false;
Expand Down Expand Up @@ -253,7 +256,7 @@ void ImageViewport::calcViewport (unsigned int texId, double ts, unsigned int fo
}
}

bool ImageViewport::loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts)
bool ImageViewport::loadImage(unsigned int *buffer, unsigned int size, bool mipmap, unsigned int format, double ts)
{
unsigned int *tmp_image;
bool ret;
Expand All @@ -270,12 +273,12 @@ bool ImageViewport::loadImage(unsigned int *buffer, unsigned int size, unsigned

if (m_avail) {
// just copy
return ImageBase::loadImage(buffer, size, format, ts);
return ImageBase::loadImage(buffer, size, mipmap, format, ts);
}
else {
tmp_image = m_image;
m_image = buffer;
calcViewport(0, ts, format);
calcViewport(0, ts, mipmap, format);
ret = m_avail;
m_image = tmp_image;
// since the image was not loaded to our buffer, it's not valid
Expand Down
6 changes: 3 additions & 3 deletions source/gameengine/VideoTexture/ImageViewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class ImageViewport : public ImageBase
void setPosition (GLint pos[2] = nullptr);

/// capture image from viewport to user buffer
virtual bool loadImage(unsigned int *buffer, unsigned int size, unsigned int format, double ts);
virtual bool loadImage(unsigned int *buffer, unsigned int size, bool mipmap, unsigned int format, double ts);

protected:
unsigned int m_width;
Expand All @@ -95,10 +95,10 @@ class ImageViewport : public ImageBase
bool m_texInit;

/// capture image from viewport
virtual void calcImage (unsigned int texId, double ts) { calcViewport(texId, ts, GL_RGBA); }
virtual void calcImage (unsigned int texId, double ts, bool mipmap, unsigned int format) { calcViewport(texId, ts, mipmap, GL_RGBA); }

/// capture image from viewport
virtual void calcViewport (unsigned int texId, double ts, unsigned int format);
virtual void calcViewport (unsigned int texId, double ts, bool mipmap, unsigned int format);

/// get viewport size
GLint * getViewportSize (void) { return m_viewport + 2; }
Expand Down
7 changes: 5 additions & 2 deletions source/gameengine/VideoTexture/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
#include <memory.h>
#include "GPU_glew.h"

#include "CM_Message.h"

extern "C" {
#include "IMB_imbuf.h"
}
Expand Down Expand Up @@ -331,9 +333,10 @@ static int Texture_init(PyObject *self, PyObject *args, PyObject *kwds)
if (texObj->m_source != nullptr)
tex->SetSource(texObj->m_source);
}
else
else {
// otherwise generate texture code
glGenTextures(1, (GLuint*)&tex->m_actTex);
}
}
catch (Exception & exp)
{
Expand Down Expand Up @@ -408,7 +411,7 @@ KX_PYMETHODDEF_DOC(Texture, refresh, "Refresh texture from source")
}

// get texture
unsigned int * texture = m_source->m_image->getImage(m_actTex, ts);
unsigned int * texture = m_source->m_image->getImage(m_actTex, ts, m_mipmap);
// if texture is available
if (texture != nullptr)
{
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/VideoTexture/VideoBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ PyObject *Video_refresh(PyImage *self, PyObject *args)
else
THRWEXCP(InvalidImageMode,S_OK);

if (!self->m_image->loadImage((unsigned int *)buffer.buf, buffer.len, format, ts)) {
if (!self->m_image->loadImage((unsigned int *)buffer.buf, buffer.len, false, format, ts)) {
PyErr_SetString(PyExc_TypeError, "Could not load the buffer, perhaps size is not compatible");
}
}
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/VideoTexture/VideoDeckLink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ void VideoDeckLink::setFrameRate (float rate)

// image calculation
// send cache frame directly to GPU
void VideoDeckLink::calcImage (unsigned int texId, double ts)
void VideoDeckLink::calcImage (unsigned int texId, double ts, bool mipmap, unsigned int format)
{
IDeckLinkVideoInputFrame* pFrame;
LockCache();
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/VideoTexture/VideoDeckLink.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class VideoDeckLink : public VideoBase
protected:
// format and codec information
/// image calculation
virtual void calcImage (unsigned int texId, double ts);
virtual void calcImage (unsigned int texId, double ts, bool mipmap, unsigned int format);

private:
void VideoFrameArrived(IDeckLinkVideoInputFrame* inputFrame);
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/VideoTexture/VideoFFmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ void VideoFFmpeg::setFrameRate (float rate)

// image calculation
// load frame from video
void VideoFFmpeg::calcImage (unsigned int texId, double ts)
void VideoFFmpeg::calcImage (unsigned int texId, double ts, bool mipmap, unsigned int format)
{
if (m_status == SourcePlaying)
{
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/VideoTexture/VideoFFmpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class VideoFFmpeg : public VideoBase
std::string m_imageName;

/// image calculation
virtual void calcImage (unsigned int texId, double ts);
virtual void calcImage (unsigned int texId, double ts, bool mipmap, unsigned int format);

/// set actual position
void setPositions (void);
Expand Down
2 changes: 1 addition & 1 deletion source/tools
Submodule tools updated from 4ace84 to b11375

0 comments on commit 0d5c77e

Please sign in to comment.