[Solved] Images sent across threads are blank

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
yonako
Prole
Posts: 2
Joined: Sun Jun 21, 2015 3:06 am

[Solved] Images sent across threads are blank

Post 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
Last edited by yonako on Sun Jun 21, 2015 9:56 pm, edited 1 time in total.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: Images sent across threads are blank

Post 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?
Last edited by Nixola on Sun Jun 21, 2015 12:16 pm, edited 1 time in total.
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
yonako
Prole
Posts: 2
Joined: Sun Jun 21, 2015 3:06 am

Re: Images sent across threads are blank

Post 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.
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Images sent across threads are blank

Post 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.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 4 guests