Object-oriented programming is not about syntax features, it's a coding and design philosphy. At its core stands the concept of an object, which is a construct that groups state with routines to act upon it (or, depending on your point of view, responses to messages). The other important aspect of OOP is encapsulation: wrapping implementation details into opaque structures and connecting them through well-defined interfaces. Pretty much everything else in OOP theory goes back to these two fundamentals.
So, any language that can somehow model objects (entities that contain both data and code) and encapsulation can be used to do OOP. For example, in C you can use function pointers to store functions in structs, and you can use the header / source file system to realize encapsulation. It's not convenient, but it is enough to do OOP. You can probably even bend something like Haskell or ML into doing OOP, and I wouldn't be surprised if someone could come up with a way of doing OOP in assembly.
Practically speaking, though, a language can be called 'object-oriented' if it provides a complete set of syntax features for explicit object-oriented programming. Typically, this means that such a language should have:
* a notion of an object
* a notion of method calling or message passing
* a comfortable and straightforward way of controlling access to object members
* a comfortable and straightforward way of defining interfaces
Consequently, I'd call a piece of code object-oriented if it adheres to OOP principles and uses the available OOP syntax.
BTW., your code example probably does use polymorphism and virtual functions, although the C syntax doesn't make it obvious. I'm not an expert on SDL, but I'd expect an
SDL_surface to be able to represent various different types of surfaces, each with its own specific set of implementations - blitting something onto a memory bitmap and blitting to a screen surface requires radically different code, but the interface (the functions that take an
SDL_surface* as an argument) remains the same. Just like that, it also implements encapsulation: you can't access a surface's underlying representation directly, you have to go through functions that know how to handle an
SDL_surface, because that's all you have. It's a nice example of how you'd do OOP in C.