Page 1 of 1

[Solved] Images sent across threads are blank

Posted: Sun Jun 21, 2015 3:21 am
by yonako
I have a simple setup where one thread loads images and the main thread fetches them as needed and draws them. (This is to ameliorate loading large images which causes framerate hiccups)

However, the images all appear as blank white when drawn. The dimensions of the white rectangle correspond correctly to the dimensions of the loaded images, so clearly the Image userdata is being passed in some form.

Here's the thread code:

Code: Select all

require "love.filesystem"
require "love.graphics"
require "love.math"

local function loadImage(winWidth, winHeight)
  local o = {}
  -- Pick random image
  local files = love.filesystem.getDirectoryItems("images")
  local i = love.math.random(1, #files)
  o.image = love.graphics.newImage('images/' .. files[i])
  print("loaded image " .. files[i])

  -- scale image
  local imgWidth = o.image:getWidth()
  local imgHeight = o.image:getHeight()
  local xScale = winWidth / imgWidth
  local yScale = winHeight / imgHeight
  o.scale = math.min(xScale, yScale)

  -- center image
  o.x = (winWidth - (imgWidth * o.scale)) / 2
  o.y = (winHeight - (imgHeight * o.scale)) / 2

  return o
end

local channel, winWidth, winHeight = ...

while true do
  local myImage = loadImage(winWidth, winHeight)
  channel:supply(myImage)
end
Here's image.lua:

Code: Select all

local P = {}

P.Image = {}

function P.Image:new(o)
  o = o or {}   -- create object if user does not provide one
  setmetatable(o, self)
  self.__index = self
  return o
end

function P.Image:draw()
  love.graphics.draw(self.image, self.x, self.y, 0, self.scale, self.scale)
end

image = P
return P
Here's the relevant main thread code:

Code: Select all

function P.newPlayer()

  -- *snip*

  o.channel = love.thread.newChannel()
  o.thread = love.thread.newThread("imageThread.lua")
  o.thread:start(o.channel, winWidth, winHeight)
  o:loadImage()

end

function P.Player:loadImage()
  self.image = image.Image:new(self.channel:demand())
end

function P.Player:draw()
  self.image:draw()
end

Re: Images sent across threads are blank

Posted: Sun Jun 21, 2015 8:31 am
by Nixola
First, I recall you shouldn't use love.graphics in any other thread than the main one; try loading imageData and passing that instead, turning it into an image in the main one. It should be faster.
Second, since you're talking about big images, are you sure they're not too big? What size are they, and what does love.graphics.getSystemLimit("texturesize") report?

Re: Images sent across threads are blank

Posted: Sun Jun 21, 2015 12:13 pm
by yonako
Thanks, that fixed it.

I'm now using love.image.newImageData() in the side thread and wrapping that with love.graphics.newImage() in the main thread. I'm curious as to why passing ImageData is okay but passing Image is not.

Also, the documentation on love.thread should probably be updated Never mind, I just noticed it says love.window AND love.graphics should only be used in the main thread. I have no idea how I missed that re-reading it multiple times.

Re: Images sent across threads are blank

Posted: Sun Jun 21, 2015 9:40 pm
by s-ol
yonako wrote:Thanks, that fixed it.

I'm now using love.image.newImageData() in the side thread and wrapping that with love.graphics.newImage() in the main thread. I'm curious as to why passing ImageData is okay but passing Image is not.

Also, the documentation on love.thread should probably be updated Never mind, I just noticed it says love.window AND love.graphics should only be used in the main thread. I have no idea how I missed that re-reading it multiple times.
To elaborate on the reason, calling love.graphics.newImage registers the Texture with the GPU whilst creating and ImageData doesn't require any involvement of your graphics card or the presence of an OpenGL context.