Can this polyomino tile the toroidal grid? Inspired by certain puzzles on Flow Free: Warps.
Background
We all know that L-triominos can't tile the 3x3 board, and P-pentominos can't tile the 5x5 board. But the situation changes if we allow the board to wrap around in both dimensions:
L-triominos can tile 3x3 toroidal grid
The 3rd tile wraps around through all four edges.
┌ ┌─┐ ┐
  │ │3 
┌─┤ └─┐
│ │2  │
│ └─┬─┘
│1  │  
└───┘ ┘

P-pentominos can tile the 5x5 toroidal grid
The 5th tile wraps around through all four edges.
┌ ┌───┬─┐ ┐
  │   │ │
┌─┘   │ └─┐
│  1  │2  │
├─────┤   │
│  3  │   │
│   ┌─┴─┬─┤
│   │   │ │
└─┬─┘   │ ╵
  │  4  │5
└ └─────┘ ┘

Note that, in both cases, wrapping around in only one dimension doesn't allow such tiling.
In case the Unicode version is hard to read, here is the ASCII version:
3 2 3
1 2 2
1 1 3

5 1 1 2 5
1 1 1 2 2
3 3 3 2 2
3 3 4 4 5
5 4 4 4 5

Challenge
Given a polyomino and the size (width and height) of the toroidal grid, determine if the polyomino can tile the toroidal grid. The polyomino can be flipped and/or rotated.
A polyomino can be given in a variety of ways:

A list of coordinates representing each cell of polyomino
A 2D grid with on/off values of your choice (in this case, you cannot assume that the size of the grid defining the polyomino matches that of the toroidal grid)

The output (true or false) can be given using the truthy/falsy values in your language of choice, or two distinct values to indicate true/false respectively.
Standard code-golf rules apply. The shortest code in bytes wins.
Test cases
The polyomino is given as the collection of # symbols.
Truthy
# (singleton, a.k.a. monomino)
5x7 (or any size)
--------
## (domino)
4x3 (or any even size)
--------
#
## (L-triomino)
3x3 (as shown above)
--------
##
### (P-pentomino)
5x5 (as shown above)
--------
##
 ## (Z-tetromino)
4x4 (left as an exercise to the reader)
--------
###
#
# (V-pentomino)
5x5
--------
####
   #
   ### (a polyomino larger than the grid is possible)
4x4
--------
###
  ###
    ### (single polyomino can cover the entire grid, and can wrap multiple times)
3x3

Falsy
## (domino)
3x5 (or any odd sizes)
--------
###
#
1x8
--------
# #
### (U-pentomino)
5x5
Python 2, 300 265 163 bytes
-35 bytes after suggestions from @xnor, @ovs, and largely @user202729 (removing evenly divisible check allowed for a one-liner + lambda)
-102 bytes following encouragement + general suggestions by @user202729

lambda l,w,h:all(w*h-len({((e-(p&4)*e//2)*1j**p+p/8+p/8/w*1j)%w%(1j*h)for e in l for p in c})for c in combinations(range(8*w*h),w*h/len(l)))
from itertools import*

Takes input as a list of complex coordinates of each cell of the polyomino. Outputs False for Truthy and True for Falsey (quirky de Morgan optimization).
Try it online with many testcases. Since this brute-forces, I have commented out a few cases to run fast enough for TIO.
Thoroughly commented:
lambda l,w,h:
    all(                        # we want any configuration to work, but De Morgan gives any(L==len) &lt;==&gt; not all(L!=len) &lt;==&gt; not all(L-len)
        w*h-len(                      # if two polyominos in a configuration overlap, then there are duplicate cells
                                    #   so the length of the set is less
                {                   # create a set consisting of each possible position+orientation of L/len(l) polyominos:
                    (                   # here, e is a single cell of the given polyomino
                        (               # reflect e across the imaginary axis if p &gt;= 4 (mod 8)
                            e-          # e-e.real*2 = e-e//.5 reflects across the Im axis
                            p&amp;4             # Only reflect if the 2^2 bit is nonzero: gives 4* or 0* following
                            *e//2           # floor(z) = z.real when z is complex, so
                        )                   # e//2 (floor division) gives z.real/2 (complex floor division only works in Python 2)
                        *1j**p          # rotate depending on the 2^0 and 2^1 bits. i**x is cyclic every 4
                        +p/8              # translate horizontally (real component) by p&gt;&gt;3 (mod this later)
                        +p/8/w*1j           # translate vertically (im component) by p&gt;&gt;3 / w
                    )%w%(1j*h)          # mod to within grid (complex mods only work in Python 2)
                    for e in l      # find where each cell e of the given polyomino goes
                    for p in c      # do this for each c (each set of position+orientation integers)
                }
        )
        for c in combinations(           # iterate c over all sets of w*h/len(l) distinct integers from 0 to 8*L-1
            range(8*w*h)              # each of these 8*L integers corresponds to a single position/orientation of a polyomino
                                    # Bits 2^0 and 2^1 give the rotation, and 2^2 gives the reflection
                                    # The higher bits give the position from 0 to L=w*h-1  ==&gt; (0,0) to (w-1,h-1)
            ,w*h/len(l)        # w*h/len(l) is the number of polyominos needed since len(l) is the number of cells per polyomino
                                    # can't switch to *[range(8*w*h)]*(w*h/len(l)) because Python 3 does not allow short complex operations as above
        )
    )
from itertools import*

A new 169-byte solution that replaces combinations with recursion:
g=lambda l,w,h,k=[]:all(g(l,w,h,k+[((e-(p&amp;4)*e//2)*1j**p+p/8+p/8/w*1j)%w%(1j*h)for e in l])for p in range(8*w*h))if w*h&gt;len(k)else len(set(k))-w*h
from itertools import*

This has the advantage of removing combinations (12 characters on its own) and one for loop, but the self-invocation takes many bytes. Currying would not save length.